diff --git a/package.json b/package.json index be23d85e8..6118eb6cc 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "setup": "npm run ats:setup && npm run mass-payout:setup", "lint": "npm run lint:js && npm run lint:sol", "lint:js": "eslint . --cache", - "lint:sol": "solhint 'packages/ats/contracts/contracts/**/*.sol' --config packages/ats/contracts/.solhint.json", + "lint:sol": "solhint 'packages/ats/contracts/contracts/**/*.sol' --config packages/ats/contracts/.solhint.json --ignore-path packages/ats/contracts/.solhintignore", "lint:fix": "eslint . --fix && npm run format", "format": "prettier --write '*.{js,mjs,cjs,ts,tsx,mts,json,md,yml,yaml}' 'packages/**/*.{js,mjs,cjs,ts,tsx,mts,json,md,yml,yaml,sol}' 'apps/**/*.{js,mjs,cjs,ts,tsx,mts,json,md,yml,yaml}' --cache", "format:check": "prettier --check '*.{js,mjs,cjs,ts,tsx,mts,json,md,yml,yaml}' 'packages/**/*.{js,mjs,cjs,ts,tsx,mts,json,md,yml,yaml,sol}' 'apps/**/*.{js,mjs,cjs,ts,tsx,mts,json,md,yml,yaml}' --cache", @@ -22,7 +22,7 @@ "clean:deps": "rimraf packages/*/node_modules packages/*/*/node_modules apps/*/node_modules apps/*/*/node_modules node_modules && echo '\n✅ Dependency files cleaned (package-lock.json preserved)'", "clean:deps:full": "npm run clean:deps && rimraf package-lock.json && echo '\n✅ All dependency files have been cleaned (including package-lock.json)'", "lint:staged:js": "eslint --cache", - "lint:staged:sol": "solhint --config packages/ats/contracts/.solhint.json", + "lint:staged:sol": "solhint --config packages/ats/contracts/.solhint.json --ignore-path packages/ats/contracts/.solhintignore", "format:staged": "prettier --check", "pre-commit": "lint-staged", "commitlint": "commitlint --edit", diff --git a/packages/ats/contracts/Configuration.ts b/packages/ats/contracts/Configuration.ts index e0584d3ba..90270888c 100644 --- a/packages/ats/contracts/Configuration.ts +++ b/packages/ats/contracts/Configuration.ts @@ -272,6 +272,7 @@ export const CONTRACT_NAMES = [ 'FreezeFacet', 'ComplianceMock', 'IdentityRegistryMock', + 'KpiOracleMock', ] as const export type ContractName = (typeof CONTRACT_NAMES)[number] export const CONTRACT_NAMES_WITH_PROXY = ['Factory', 'BusinessLogicResolver'] diff --git a/packages/ats/contracts/contracts/layer_0/ERC3643/ERC3643StorageWrapper1.sol b/packages/ats/contracts/contracts/layer_0/ERC3643/ERC3643StorageWrapper1.sol index 67fba9ff0..78f349554 100644 --- a/packages/ats/contracts/contracts/layer_0/ERC3643/ERC3643StorageWrapper1.sol +++ b/packages/ats/contracts/contracts/layer_0/ERC3643/ERC3643StorageWrapper1.sol @@ -214,7 +214,6 @@ import {_AGENT_ROLE} from '../constants/roles.sol'; import { IERC3643Basic } from '../../layer_1/interfaces/ERC3643/IERC3643Basic.sol'; -import {PauseStorageWrapper} from '../core/pause/PauseStorageWrapper.sol'; import { IAccessControl } from '../../layer_1/interfaces/accessControl/IAccessControl.sol'; @@ -233,13 +232,15 @@ import { } from '../constants/storagePositions.sol'; import {ICompliance} from '../../layer_1/interfaces/ERC3643/ICompliance.sol'; import {LowLevelCall} from '../common/libraries/LowLevelCall.sol'; -import {PauseStorageWrapper} from '../core/pause/PauseStorageWrapper.sol'; +import { + InterestRateKpiStorageWrapper +} from '../interestRate/kpi/InterestRateKpiStorageWrapper.sol'; import {Strings} from '@openzeppelin/contracts/utils/Strings.sol'; import {_AGENT_ROLE} from '../constants/roles.sol'; abstract contract ERC3643StorageWrapper1 is IERC3643StorageWrapper, - PauseStorageWrapper + InterestRateKpiStorageWrapper { using LowLevelCall for address; diff --git a/packages/ats/contracts/contracts/layer_0/constants/storagePositions.sol b/packages/ats/contracts/contracts/layer_0/constants/storagePositions.sol index 5c04dd400..364e1b9e6 100644 --- a/packages/ats/contracts/contracts/layer_0/constants/storagePositions.sol +++ b/packages/ats/contracts/contracts/layer_0/constants/storagePositions.sol @@ -288,3 +288,6 @@ bytes32 constant _ERC3643_STORAGE_POSITION = 0xba82ce8c38a926a01a84988222ab779cf // keccak256('security.token.standard.resolverProxy.storage'); bytes32 constant _RESOLVER_PROXY_STORAGE_POSITION = 0x4833864335c8f29dd85e3f7a36869cb90d5dc7167ae5000f7e1ce4d7c15d14ad; + +// keccak256('security.token.standard.interest.rate.kpi.storage'); +bytes32 constant _INTEREST_RATE_KPI = 0xfc9577e9a0b1943154bf0811f3eb0d1d3e2f5a2eddb6b6b6d4226f5c21a267b3; diff --git a/packages/ats/contracts/contracts/layer_0/interestRate/kpi/InterestRateKpiStorageWrapper.sol b/packages/ats/contracts/contracts/layer_0/interestRate/kpi/InterestRateKpiStorageWrapper.sol new file mode 100644 index 000000000..e06faf2c8 --- /dev/null +++ b/packages/ats/contracts/contracts/layer_0/interestRate/kpi/InterestRateKpiStorageWrapper.sol @@ -0,0 +1,337 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +import {LowLevelCall} from '../../common/libraries/LowLevelCall.sol'; +import {PauseStorageWrapper} from '../../core/pause/PauseStorageWrapper.sol'; +import { + IInterestRateKpi, + InterestRateKpiDataStorage, + InterestRateKpiDataDetails +} from '../../../layer_1/interfaces/interestRate/kpi/IInterestRateKpi.sol'; +import {_INTEREST_RATE_KPI} from '../../constants/storagePositions.sol'; +import {IKpiOracle} from '../../../layer_1/interfaces/interestRate/kpi/IKpiOracle.sol'; +import {IInterestRateKpiStorageWrapper} from '../../../layer_1/interfaces/interestRate/kpi/IInterestRateKpiStorageWrapper.sol'; + +abstract contract InterestRateKpiStorageWrapper is + IInterestRateKpiStorageWrapper, + PauseStorageWrapper +{ + using LowLevelCall for address; + + uint256 internal constant _DECIMALS_PRECISION = 1e18; + + function _setIneterestRateKpiData( + InterestRateKpiDataDetails memory _newData + ) internal { + _interestRateKpiStorage().kpiOracle = _newData.kpiOracle; + _interestRateKpiStorage().interestRateData = _newData.interestRateData; + _interestRateKpiStorage().impactLimits = _newData.impactLimits; + _interestRateKpiStorage().reportData = _newData.reportData; + _interestRateKpiStorage().lastReportTimestamp = _newData + .lastReportTimestamp; + } + + function _calculateInterestRateKpi( + uint256 _fromDate, + uint256 _toDate + ) internal returns (uint256) { + InterestRateKpiDataStorage memory params = _interestRateKpiStorage(); + if (params.kpiOracle == address(0)) { + return params.interestRateData.limits.base; + } + + uint256 timestamp = _blockTimestamp(); + + if (timestamp < params.interestRateData.startPeriod) + return params.interestRateData.startRate; + + uint256 impactData; + bool reportFound; + + if (_timeElapsed() >= params.reportData.resetPeriod) { + (impactData, reportFound) = abi.decode( + params.kpiOracle.functionStaticCall( + abi.encodeWithSelector( + IKpiOracle.getImpactData.selector, + _fromDate, + _toDate + ), + IInterestRateKpi.CallToKpiOracleFailed.selector + ), + (uint256, bool) + ); + _interestRateKpiStorage().lastReportTimestamp = _blockTimestamp(); + emit LastPeriodTimestampUpdated(); + // Missed report penalty + if (!reportFound) { + uint256 newRate = params.interestRateData.limits.base + + params.reportData.missedPenalty; + + _interestRateKpiStorage().cahchedInterestRate = newRate; + + return newRate; + } + } else { + return params.cahchedInterestRate; + } + + int256 impactDelta = int256(impactData) - + int256(params.impactLimits.baseLine); + + uint256 targetRate = params.interestRateData.limits.base; + + if (impactDelta >= 0) { + uint256 impactDeltaRate = (uint256(impactDelta) * + _DECIMALS_PRECISION) / + (params.impactLimits.maxDeviationCap - + params.impactLimits.baseLine); + targetRate = + params.interestRateData.limits.base - + (((params.interestRateData.limits.base - + params.interestRateData.limits.marginFloor) * + impactDeltaRate) / _DECIMALS_PRECISION); + } else { + uint256 impactDeltaRate = (uint256(-impactDelta) * + _DECIMALS_PRECISION) / + (params.impactLimits.baseLine - + params.impactLimits.maxDeviationFloor); + targetRate = + params.interestRateData.limits.base + + (((params.interestRateData.limits.marginCap - + params.interestRateData.limits.base) * impactDeltaRate) / + _DECIMALS_PRECISION); + } + + if (targetRate > params.interestRateData.limits.marginCap) { + targetRate = params.interestRateData.limits.marginCap; + } + if (targetRate < params.interestRateData.limits.marginFloor) { + targetRate = params.interestRateData.limits.marginFloor; + } + _interestRateKpiStorage().cahchedInterestRate = targetRate; + + return targetRate; + } + + function _timeElapsed() internal view returns (uint256 seconds_) { + return + _blockTimestamp() - _interestRateKpiStorage().lastReportTimestamp; + } + + function _interestRateKpiStorage() + internal + pure + returns (InterestRateKpiDataStorage storage interestRateKpiData_) + { + bytes32 position = _INTEREST_RATE_KPI; + // solhint-disable-next-line no-inline-assembly + assembly { + interestRateKpiData_.slot := position + } + } +} diff --git a/packages/ats/contracts/contracts/layer_1/constants/resolverKeys.sol b/packages/ats/contracts/contracts/layer_1/constants/resolverKeys.sol index ce48be0ec..f0e30a2d3 100644 --- a/packages/ats/contracts/contracts/layer_1/constants/resolverKeys.sol +++ b/packages/ats/contracts/contracts/layer_1/constants/resolverKeys.sol @@ -315,3 +315,6 @@ bytes32 constant _ERC3643_BATCH_RESOLVER_KEY = 0x9e671b494908a7523ee4e531ae7b707 // keccak256('security.token.standard.freeze.resolverKey'); bytes32 constant _FREEZE_RESOLVER_KEY = 0x49f765e7155d979a148049c2a0ebed5e028b11799061897a255f99314f0bd3f1; + +// keccak256("security.token.standard.interest.rate.kpi.resolverKey") +bytes32 constant _INTEREST_RATE_KPI_RESOLVER_KEY = 0x4caa1fdf5cec6844c6c1ae87aa2b6cf09aa6ffd7d94d2514006cc37806f5b9d9; diff --git a/packages/ats/contracts/contracts/layer_1/constants/roles.sol b/packages/ats/contracts/contracts/layer_1/constants/roles.sol index 63c1f3c84..4523c167b 100644 --- a/packages/ats/contracts/contracts/layer_1/constants/roles.sol +++ b/packages/ats/contracts/contracts/layer_1/constants/roles.sol @@ -284,3 +284,6 @@ bytes32 constant _TREX_OWNER_ROLE = 0x03ce2fdc316501dd97f5219e6ad908a3238f1e90f9 // keccak256('security.token.standard.role.maturity.redeemer'); bytes32 constant _MATURITY_REDEEMER_ROLE = 0xa0d696902e9ed231892dc96649f0c62b808a1cb9dd1269e78e0adc1cc4b8358c; + +// keccak256('security.token.standard.role.interest.rate.kpi.manager'); +bytes32 constant _INTEREST_RATE_KPI_MANAGER_ROLE = 0xa315b3ee5eec2e86b908b4fcab908df367aa4b21a9732cd3fa5c1aa1928f4ec6; diff --git a/packages/ats/contracts/contracts/layer_1/interestRate/kpi/InterestRateKpi.sol b/packages/ats/contracts/contracts/layer_1/interestRate/kpi/InterestRateKpi.sol new file mode 100644 index 000000000..9381eda04 --- /dev/null +++ b/packages/ats/contracts/contracts/layer_1/interestRate/kpi/InterestRateKpi.sol @@ -0,0 +1,240 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// SPDX-License-Identifier: BSD-3-Clause-Attribution +pragma solidity 0.8.18; + +import { + IInterestRateKpi, + InterestRateKpiDataDetails +} from '../../interfaces/interestRate/kpi/IInterestRateKpi.sol'; +import {_INTEREST_RATE_KPI_MANAGER_ROLE} from '../../../layer_1/constants/roles.sol'; +import {Common} from '../../common/Common.sol'; + +abstract contract InterestRateKpi is IInterestRateKpi, Common { + function initialize_InterestRateKpi( + InterestRateKpiDataDetails memory _initData + ) + external + override + onlyUninitialized(_interestRateKpiStorage().initialized) + { + _setIneterestRateKpiData(_initData); + } + + function setIneterestRateKpiData( + InterestRateKpiDataDetails memory _newData + ) external onlyRole(_INTEREST_RATE_KPI_MANAGER_ROLE) { + _setIneterestRateKpiData(_newData); + emit InterestRateKpiDataChanged(_newData); + } + + function calculateInterestRate( + uint256 _fromDate, + uint256 _toDate + ) external returns (uint256 interestRate_) { + interestRate_ = _calculateInterestRateKpi(_fromDate, _toDate); + } +} diff --git a/packages/ats/contracts/contracts/layer_1/interestRate/kpi/InterestRateKpiFacet.sol b/packages/ats/contracts/contracts/layer_1/interestRate/kpi/InterestRateKpiFacet.sol new file mode 100644 index 000000000..e602b98fd --- /dev/null +++ b/packages/ats/contracts/contracts/layer_1/interestRate/kpi/InterestRateKpiFacet.sol @@ -0,0 +1,251 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// SPDX-License-Identifier: BSD-3-Clause-Attribution +pragma solidity 0.8.18; + +import {_INTEREST_RATE_KPI_RESOLVER_KEY} from '../../constants/resolverKeys.sol'; +import {IStaticFunctionSelectors} from '../../../interfaces/resolver/resolverProxy/IStaticFunctionSelectors.sol'; +import {IInterestRateKpi} from '../../interfaces/interestRate/kpi/IInterestRateKpi.sol'; +import {InterestRateKpi} from './InterestRateKpi.sol'; + +contract InterestRateKpiFacet is IStaticFunctionSelectors, InterestRateKpi { + function getStaticResolverKey() + external + pure + override + returns (bytes32 staticResolverKey_) + { + staticResolverKey_ = _INTEREST_RATE_KPI_RESOLVER_KEY; + } + + function getStaticFunctionSelectors() + external + pure + override + returns (bytes4[] memory staticFunctionSelectors_) + { + uint256 selectorIndex; + staticFunctionSelectors_ = new bytes4[](3); + staticFunctionSelectors_[selectorIndex++] = this + .calculateInterestRate + .selector; + staticFunctionSelectors_[selectorIndex++] = this + .initialize_InterestRateKpi + .selector; + } + + function getStaticInterfaceIds() + external + pure + override + returns (bytes4[] memory staticInterfaceIds_) + { + staticInterfaceIds_ = new bytes4[](1); + uint256 selectorsIndex; + staticInterfaceIds_[selectorsIndex++] = type(IInterestRateKpi) + .interfaceId; + } +} diff --git a/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IInterestRateKpi.sol b/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IInterestRateKpi.sol new file mode 100644 index 000000000..661efa60c --- /dev/null +++ b/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IInterestRateKpi.sol @@ -0,0 +1,264 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +struct InteresRateLimits { + uint256 marginCap; + uint256 base; + uint256 marginFloor; +} + +struct InterestRateData { + InteresRateLimits limits; + uint256 startPeriod; + uint256 startRate; +} + +struct ImpactLimits { + uint256 maxDeviationCap; + uint256 baseLine; + uint256 maxDeviationFloor; +} + +struct ReportData { + uint256 resetPeriod; + uint256 missedPenalty; +} + +struct InterestRateKpiDataStorage { + bool initialized; + address kpiOracle; + InterestRateData interestRateData; + ImpactLimits impactLimits; + ReportData reportData; + uint256 lastReportTimestamp; + uint256 cahchedInterestRate; +} + +struct InterestRateKpiDataDetails { + address kpiOracle; + InterestRateData interestRateData; + ImpactLimits impactLimits; + ReportData reportData; + uint256 lastReportTimestamp; +} + +interface IInterestRateKpi { + event KpiOracleSet(address indexed _oldOracle, address indexed _newOracle); + event InterestRateKpiDataChanged(InterestRateKpiDataDetails _newData); + + error CallToKpiOracleFailed(); + + function initialize_InterestRateKpi( + InterestRateKpiDataDetails memory _initData + ) external; + + function calculateInterestRate( + uint256 _fromDate, + uint256 _toDate + ) external returns (uint256 interestRate_); +} diff --git a/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IInterestRateKpiStorageWrapper.sol b/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IInterestRateKpiStorageWrapper.sol new file mode 100644 index 000000000..416a6b97b --- /dev/null +++ b/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IInterestRateKpiStorageWrapper.sol @@ -0,0 +1,211 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// SPDX-License-Identifier: MIT +pragma solidity 0.8.18; + +interface IInterestRateKpiStorageWrapper { + event LastPeriodTimestampUpdated(); +} diff --git a/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IKpiOracle.sol b/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IKpiOracle.sol new file mode 100644 index 000000000..63580e2f0 --- /dev/null +++ b/packages/ats/contracts/contracts/layer_1/interfaces/interestRate/kpi/IKpiOracle.sol @@ -0,0 +1,214 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +// SPDX-License-Identifier: UNLICENSED +pragma solidity 0.8.18; + +interface IKpiOracle { + function getImpactData( + uint256 _fromDate, + uint256 _toDate + ) external view returns (uint256 impactData_, bool reportFound_); +} diff --git a/packages/ats/contracts/contracts/layer_2/bond/Bond.sol b/packages/ats/contracts/contracts/layer_2/bond/Bond.sol index 5f317b8ad..4bd3a2124 100644 --- a/packages/ats/contracts/contracts/layer_2/bond/Bond.sol +++ b/packages/ats/contracts/contracts/layer_2/bond/Bond.sol @@ -215,9 +215,7 @@ import { _BOND_MANAGER_ROLE, _MATURITY_REDEEMER_ROLE } from '../../layer_1/constants/roles.sol'; -import { - IStaticFunctionSelectors -} from '../../interfaces/resolver/resolverProxy/IStaticFunctionSelectors.sol'; +import {IStaticFunctionSelectors} from '../../interfaces/resolver/resolverProxy/IStaticFunctionSelectors.sol'; abstract contract Bond is IBond, IStaticFunctionSelectors, BondStorageWrapper { function redeemAtMaturityByPartition( @@ -271,6 +269,16 @@ abstract contract Bond is IBond, IStaticFunctionSelectors, BondStorageWrapper { ); } + function setInterestRateMode( + InterestRateMode _newInterestRateMode + ) external override onlyRole(_CORPORATE_ACTION_ROLE) { + InterestRateMode oldInterestRateMode = _setInterestRateMode( + _newInterestRateMode + ); + + emit InterestRateModeChanged(oldInterestRateMode, _newInterestRateMode); + } + /** * @dev Updates the maturity date of the bond. * @param _newMaturityDate The new maturity date to be set. @@ -294,6 +302,18 @@ abstract contract Bond is IBond, IStaticFunctionSelectors, BondStorageWrapper { return success_; } + function getCouponFor( + uint256 _couponID, + address _account + ) + external + override + onlyMatchingActionType(COUPON_CORPORATE_ACTION_TYPE, _couponID - 1) + returns (CouponFor memory couponFor_) + { + return _getCouponFor(_couponID, _account); + } + function getBondDetails() external view @@ -324,19 +344,6 @@ abstract contract Bond is IBond, IStaticFunctionSelectors, BondStorageWrapper { return _getCoupon(_couponID); } - function getCouponFor( - uint256 _couponID, - address _account - ) - external - view - override - onlyMatchingActionType(COUPON_CORPORATE_ACTION_TYPE, _couponID - 1) - returns (CouponFor memory couponFor_) - { - return _getCouponFor(_couponID, _account); - } - function getCouponCount() external view diff --git a/packages/ats/contracts/contracts/layer_2/bond/BondStorageWrapper.sol b/packages/ats/contracts/contracts/layer_2/bond/BondStorageWrapper.sol index b70d82f5d..dedf84d3a 100644 --- a/packages/ats/contracts/contracts/layer_2/bond/BondStorageWrapper.sol +++ b/packages/ats/contracts/contracts/layer_2/bond/BondStorageWrapper.sol @@ -211,9 +211,7 @@ import {COUPON_CORPORATE_ACTION_TYPE} from '../constants/values.sol'; import {IBond} from '../interfaces/bond/IBond.sol'; import {Common} from '../../layer_1/common/Common.sol'; import {IBondStorageWrapper} from '../interfaces/bond/IBondStorageWrapper.sol'; -import { - EnumerableSet -} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; +import {EnumerableSet} from '@openzeppelin/contracts/utils/structs/EnumerableSet.sol'; abstract contract BondStorageWrapper is IBondStorageWrapper, Common { using EnumerableSet for EnumerableSet.Bytes32Set; @@ -286,6 +284,62 @@ abstract contract BondStorageWrapper is IBondStorageWrapper, Common { return true; } + function _getCouponFor( + uint256 _couponID, + address _account + ) internal returns (IBond.CouponFor memory couponFor_) { + IBond.RegisteredCoupon memory registeredCoupon = _getCoupon(_couponID); + + IBond.CouponDetailsData memory couponDetails = _getCouponDetails(); + + if ( + couponDetails.interestRateMode == IBond.InterestRateMode.FIXED_KPI + ) { + couponFor_.rate = _calculateInterestRateKpi( + registeredCoupon.coupon.recordDate, + registeredCoupon.coupon.recordDate + + registeredCoupon.coupon.period + ); + } else { + couponFor_.rate = couponDetails.couponRate; + } + + couponFor_.recordDate = registeredCoupon.coupon.recordDate; + couponFor_.executionDate = registeredCoupon.coupon.executionDate; + + if (registeredCoupon.coupon.recordDate < _blockTimestamp()) { + couponFor_.recordDateReached = true; + + couponFor_.tokenBalance = (registeredCoupon.snapshotId != 0) + ? (_balanceOfAtSnapshot(registeredCoupon.snapshotId, _account) + + _lockedBalanceOfAtSnapshot( + registeredCoupon.snapshotId, + _account + ) + + _heldBalanceOfAtSnapshot( + registeredCoupon.snapshotId, + _account + )) + + _clearedBalanceOfAtSnapshot( + registeredCoupon.snapshotId, + _account + ) + : (_balanceOf(_account) + + _getLockedAmountFor(_account) + + _getHeldAmountFor(_account)) + + _getClearedAmountFor(_account); + + couponFor_.decimals = _decimalsAdjusted(); + } + } + + function _setInterestRateMode( + IBond.InterestRateMode _newInterestRateMode + ) internal returns (IBond.InterestRateMode oldInterestRateMode_) { + oldInterestRateMode_ = _bondStorage().couponDetail.interestRateMode; + _bondStorage().couponDetail.interestRateMode = _newCouponType; + } + function _getBondDetails() internal view @@ -321,43 +375,6 @@ abstract contract BondStorageWrapper is IBondStorageWrapper, Common { registeredCoupon_.snapshotId = _getSnapshotID(actionId); } - - function _getCouponFor( - uint256 _couponID, - address _account - ) internal view returns (IBond.CouponFor memory couponFor_) { - IBond.RegisteredCoupon memory registeredCoupon = _getCoupon(_couponID); - - couponFor_.rate = registeredCoupon.coupon.rate; - couponFor_.recordDate = registeredCoupon.coupon.recordDate; - couponFor_.executionDate = registeredCoupon.coupon.executionDate; - - if (registeredCoupon.coupon.recordDate < _blockTimestamp()) { - couponFor_.recordDateReached = true; - - couponFor_.tokenBalance = (registeredCoupon.snapshotId != 0) - ? (_balanceOfAtSnapshot(registeredCoupon.snapshotId, _account) + - _lockedBalanceOfAtSnapshot( - registeredCoupon.snapshotId, - _account - ) + - _heldBalanceOfAtSnapshot( - registeredCoupon.snapshotId, - _account - )) + - _clearedBalanceOfAtSnapshot( - registeredCoupon.snapshotId, - _account - ) - : (_balanceOf(_account) + - _getLockedAmountFor(_account) + - _getHeldAmountFor(_account)) + - _getClearedAmountFor(_account); - - couponFor_.decimals = _decimalsAdjusted(); - } - } - function _getCouponCount() internal view returns (uint256 couponCount_) { return _getCorporateActionCountByType(COUPON_CORPORATE_ACTION_TYPE); } diff --git a/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBond.sol b/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBond.sol index 04aac1855..ffe2c8120 100644 --- a/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBond.sol +++ b/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBond.sol @@ -214,16 +214,23 @@ interface IBond { uint256 maturityDate; } + enum InterestRateMode { + FIXED, + FIXED_KPI + } + struct CouponDetailsData { uint256 couponFrequency; uint256 couponRate; uint256 firstCouponDate; + InterestRateMode interestRateMode; } struct Coupon { uint256 recordDate; uint256 executionDate; uint256 rate; + uint256 period; } struct RegisteredCoupon { @@ -240,6 +247,11 @@ interface IBond { bool recordDateReached; } + event InterestRateModeChanged( + InterestRateMode oldInterestRateMode, + InterestRateMode newInterestRateMode + ); + function redeemAtMaturityByPartition( address _tokenHolder, bytes32 _partition, @@ -254,6 +266,13 @@ interface IBond { uint256 _maturityDate ) external returns (bool success_); + function setInterestRateMode(InterestRateMode _couponType) external; + + function getCouponFor( + uint256 _couponID, + address _account + ) external returns (CouponFor memory couponFor_); + function getBondDetails() external view @@ -268,11 +287,6 @@ interface IBond { uint256 _couponID ) external view returns (RegisteredCoupon memory registeredCoupon_); - function getCouponFor( - uint256 _couponID, - address _account - ) external view returns (CouponFor memory couponFor_); - function getCouponCount() external view returns (uint256 couponCount_); function getCouponHolders( diff --git a/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBondStorageWrapper.sol b/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBondStorageWrapper.sol index a4cc68aa2..01968ec0b 100644 --- a/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBondStorageWrapper.sol +++ b/packages/ats/contracts/contracts/layer_2/interfaces/bond/IBondStorageWrapper.sol @@ -221,9 +221,15 @@ interface IBondStorageWrapper { uint256 indexed maturityDate, uint256 indexed previousMaturityDate ); + event KpiOracleSet( + address indexed bondId, + address indexed operator, + address indexed newKpiOracle + ); error CouponCreationFailed(); error CouponFirstDateWrong(); error CouponFrequencyWrong(); + error CouponRateCalculationError(); error BondMaturityDateWrong(); } diff --git a/packages/ats/contracts/scripts/constants.ts b/packages/ats/contracts/scripts/constants.ts index a6c4bd2c2..38590d816 100644 --- a/packages/ats/contracts/scripts/constants.ts +++ b/packages/ats/contracts/scripts/constants.ts @@ -288,6 +288,9 @@ export const MATURITY_REDEEMER_ROLE = '0xa0d696902e9ed231892dc96649f0c62b808a1cb9dd1269e78e0adc1cc4b8358c' export const TREX_OWNER_ROLE = '0x03ce2fdc316501dd97f5219e6ad908a3238f1e90f910aa17b627f801a6aafab7' +export const KPI_ORACLE_MANAGER_ROLE = + '0xbc2df017463cc199f674d1cac4b2628ac636da6f836c4ec94d345aa2e824c42e' + // * Errors export const IS_PAUSED_ERROR_ID = '0x40' export const OPERATOR_ACCOUNT_BLOCKED_ERROR_ID = '0x41' diff --git a/packages/ats/contracts/scripts/factory.ts b/packages/ats/contracts/scripts/factory.ts index 465490d50..c8268da52 100644 --- a/packages/ats/contracts/scripts/factory.ts +++ b/packages/ats/contracts/scripts/factory.ts @@ -265,6 +265,7 @@ export interface BondDetailsData { nominalValue: number startingDate: number maturityDate: number + kpiOracle: string } export interface CouponDetailsData { @@ -506,6 +507,7 @@ export async function setBondData({ externalKycLists, compliance, identityRegistry, + kpiOracle, }: { adminAccount: string isWhiteList: boolean @@ -534,6 +536,7 @@ export async function setBondData({ externalKycLists?: string[] compliance?: string identityRegistry?: string + kpiOracle?: string }) { let rbacs: Rbac[] = [] @@ -585,6 +588,7 @@ export async function setBondData({ nominalValue: nominalValue, startingDate: startingDate, maturityDate: maturityDate, + kpiOracle: kpiOracle ?? ADDRESS_ZERO, } const couponDetails: CouponDetailsData = { @@ -756,6 +760,7 @@ export async function deployBondFromFactory({ businessLogicResolver, compliance, identityRegistry, + kpiOracle, }: { adminAccount: string isWhiteList: boolean @@ -787,6 +792,7 @@ export async function deployBondFromFactory({ businessLogicResolver: string compliance?: string identityRegistry?: string + kpiOracle?: string }) { const bondData = await setBondData({ adminAccount, @@ -813,6 +819,7 @@ export async function deployBondFromFactory({ businessLogicResolver, compliance, identityRegistry, + kpiOracle, }) const factoryRegulationData = await setFactoryRegulationData( diff --git a/packages/ats/contracts/tasks/Arguments.ts b/packages/ats/contracts/tasks/Arguments.ts index 11ac228c9..720d2d812 100644 --- a/packages/ats/contracts/tasks/Arguments.ts +++ b/packages/ats/contracts/tasks/Arguments.ts @@ -233,6 +233,7 @@ export interface CreateVcArgs { // * Deploy export interface DeployArgs extends WithSigner { contractName: string + constructorArgs: string[] } export interface DeployAllArgs extends WithSigner { diff --git a/packages/ats/contracts/tasks/deploy.ts b/packages/ats/contracts/tasks/deploy.ts index b673c4b50..cb3f53f46 100644 --- a/packages/ats/contracts/tasks/deploy.ts +++ b/packages/ats/contracts/tasks/deploy.ts @@ -405,6 +405,12 @@ task('deploy', 'Deploy new contract') undefined, types.string ) + .addOptionalVariadicPositionalParam( + 'constructorArgs', + 'Arguments for the contract constructor', + undefined, + types.string + ) .addOptionalParam( 'privateKey', 'The private key of the account in raw hexadecimal format', @@ -450,6 +456,7 @@ task('deploy', 'Deploy new contract') new DeployContractCommand({ name: contractName, signer, + args: args.constructorArgs, }) ) diff --git a/packages/ats/contracts/test/unitTests/layer_1/bond/bond.test.ts b/packages/ats/contracts/test/unitTests/layer_1/bond/bond.test.ts index bc5ff87f4..92ef402b4 100644 --- a/packages/ats/contracts/test/unitTests/layer_1/bond/bond.test.ts +++ b/packages/ats/contracts/test/unitTests/layer_1/bond/bond.test.ts @@ -231,6 +231,7 @@ import { ControlList, ClearingActionsFacet, ProtectedPartitions, + Snapshots, } from '@typechain' import { CORPORATE_ACTION_ROLE, @@ -256,6 +257,10 @@ import { CONTROL_LIST_ROLE, CLEARING_ROLE, PROTECTED_PARTITIONS_ROLE, + deployContract, + DeployContractCommand, + SNAPSHOT_ROLE, + KPI_ORACLE_MANAGER_ROLE, } from '@scripts' import { grantRoleAndPauseToken } from '@test' import { loadFixture } from '@nomicfoundation/hardhat-network-helpers' @@ -311,6 +316,8 @@ describe('Bond Tests', () => { let controlListFacet: ControlList let clearingActionsFacet: ClearingActionsFacet let protectedPartitionsFacet: ProtectedPartitions + let kpiOracleMockAddress: string + let snapshotsFacet: Snapshots function set_initRbacs(): Rbac[] { const rbacPause: Rbac = { @@ -341,6 +348,10 @@ describe('Bond Tests', () => { role: PROTECTED_PARTITIONS_ROLE, members: [account_A], } + const rbacSnapshots: Rbac = { + role: SNAPSHOT_ROLE, + members: [account_A], + } return [ rbacPause, rbacKYC, @@ -349,6 +360,7 @@ describe('Bond Tests', () => { rbacSSI, rbacClearing, rbacProtectedPartitions, + rbacSnapshots, ] } @@ -371,6 +383,11 @@ describe('Bond Tests', () => { diamond.address, signer_A ) + snapshotsFacet = await ethers.getContractAt( + 'Snapshots', + diamond.address, + signer_A + ) await ssiManagementFacet.connect(signer_A).addIssuer(account_A) controlListFacet = await ethers.getContractAt( @@ -451,6 +468,16 @@ describe('Bond Tests', () => { }) ) + kpiOracleMockAddress = ( + await deployContract( + new DeployContractCommand({ + name: 'KpiOracleMock', + signer: signer_A, + args: [], + }) + ) + ).address + factory = deployedContracts.factory.contract businessLogicResolver = deployedContracts.businessLogicResolver.contract }) @@ -1056,6 +1083,146 @@ describe('Bond Tests', () => { expect(couponHolders.length).to.equal(couponTotalHolders) } }) + + describe('KPI oracle', () => { + it('GIVEN kpi oracle set during deployment THEN the address is correctly set', async () => { + const init_rbacs: Rbac[] = set_initRbacs() + + const newDiamond = await deployBondFromFactory({ + adminAccount: account_A, + isWhiteList: false, + isControllable: true, + arePartitionsProtected: false, + clearingActive: false, + internalKycActivated: true, + isMultiPartition: false, + name: 'TEST_AccessControl', + symbol: 'TAC', + decimals: 6, + isin: isinGenerator(), + currency: '0x455552', + numberOfUnits, + nominalValue: 100, + startingDate, + maturityDate, + couponFrequency: frequency, + couponRate: rate, + firstCouponDate, + regulationType: RegulationType.REG_D, + regulationSubType: RegulationSubType.REG_D_506_C, + countriesControlListType, + listOfCountries, + info, + init_rbacs, + factory, + businessLogicResolver: businessLogicResolver.address, + kpiOracle: kpiOracleMockAddress, + }) + + const bondDetails = await bondFacet + .attach(newDiamond.address) + .getBondDetails() + expect(bondDetails.kpiOracle).to.equal(kpiOracleMockAddress) + }) + it('GIVEN a user without the KPI_ORACLE_MANAGER_ROLE role WHEN setting a new interest rate calculator THEN the transaction reverts with AccountHasNoRole', async () => { + await expect( + bondFacet + .connect(signer_C) + .setKpiOracle(kpiOracleMockAddress) + ).to.revertedWithCustomError(bondFacet, 'AccountHasNoRole') + }) + + it('GIVEN a user with the KPI_ORACLE_MANAGER_ROLE role WHEN setting a new interest rate calculator THEN the transaction succeeds', async () => { + await accessControlFacet.grantRole( + KPI_ORACLE_MANAGER_ROLE, + account_C + ) + await expect( + bondFacet + .connect(signer_C) + .setKpiOracle(kpiOracleMockAddress) + ) + .to.emit(bondFacet, 'kpiOracleSet') + .withArgs( + bondFacet.address, + account_C, + kpiOracleMockAddress + ) + + const bondDetails = await bondFacet.getBondDetails() + expect(bondDetails.kpiOracle).to.equal(kpiOracleMockAddress) + }) + + // it('GIVEN a coupon set when retrieving its interest rate THEN the adjusted value is returned', async () => { + // await accessControlFacet.grantRole( + // IR_CALCULATOR_MANAGER_ROLE, + // account_C + // ) + // await accessControlFacet.grantRole( + // CORPORATE_ACTION_ROLE, + // account_C + // ) + // await bondFacet + // .connect(signer_C) + // .setkpiOracle(kpiOracleMockAddress) + // await timeTravelFacet.changeSystemTimestamp( + // firstCouponDate + 1 + // ) + // await snapshotsFacet.takeSnapshot() + // const couponFor = await bondFacet.getCouponFor(1, account_A) + // expect(couponFor.rate).to.equal(rate + 1) // (+1) hardcoded in the mock + // }) + + it('GIVEN a failed called to the calculator THEN transaction reverts with ', async () => { + const kpiOracleMock = await ethers.getContractAt( + 'kpiOracleMock', + kpiOracleMockAddress + ) + kpiOracleMock.setRevertFlag(true) + + await accessControlFacet.grantRole( + KPI_ORACLE_MANAGER_ROLE, + account_C + ) + await accessControlFacet.grantRole( + CORPORATE_ACTION_ROLE, + account_C + ) + await bondFacet + .connect(signer_C) + .setKpiOracle(kpiOracleMockAddress) + await timeTravelFacet.changeSystemTimestamp( + firstCouponDate + 1 + ) + await snapshotsFacet.takeSnapshot() + + let caught + try { + await bondFacet.getCouponFor(1, account_A) + } catch (err: any) { + caught = err + } + const returnedSelector = (caught.data as string).slice( + 0, + 10 + ) + const outerSelector = bondFacet.interface.getSighash( + 'CallToKpiOracleFailed()' + ) + expect(returnedSelector).to.equal(outerSelector) + const targetErrorSelector = + kpiOracleMock.interface.getSighash( + 'KpiOracleMock_Error()' + ) + const targetErrorArgs: any = [] // No args in target contract custom error + const args = ethers.utils.solidityPack( + ['bytes4', 'bytes'], + [targetErrorSelector, targetErrorArgs] + ) + const returnedArgs = (caught.data as string).slice(10) // Skip custom error selector + expect(returnedArgs).to.equal(args.slice(2)) + }) + }) }) }) describe('Multi Partition', () => { diff --git a/packages/ats/sdk/__tests__/fixtures/bond/BondFixture.ts b/packages/ats/sdk/__tests__/fixtures/bond/BondFixture.ts index aca82eb76..ed7fe94f2 100644 --- a/packages/ats/sdk/__tests__/fixtures/bond/BondFixture.ts +++ b/packages/ats/sdk/__tests__/fixtures/bond/BondFixture.ts @@ -246,6 +246,8 @@ import { GetCouponHoldersQuery } from '@query/bond/coupons/getCouponHolders/GetC import { GetTotalCouponHoldersQuery } from '@query/bond/coupons/getTotalCouponHolders/GetTotalCouponHoldersQuery'; import GetCouponHoldersRequest from '@port/in/request/bond/GetCouponHoldersRequest'; import GetTotalCouponHoldersRequest from '@port/in/request/bond/GetTotalCouponHoldersRequest'; +import { SetKpiOracleCommand } from '@command/bond/coupon/kpiOracle/SetKpiOracleCommand'; +import SetKpiOracleRequest from '@port/in/request/bond/SetKpiOracleRequest'; export const SetCouponCommandFixture = createFixture( (command) => { @@ -262,6 +264,13 @@ export const SetCouponCommandFixture = createFixture( }, ); +export const SetKpiOracleCommandFixture = createFixture( + (command) => { + command.securityId.as(() => HederaIdPropsFixture.create().value); + command.kpiOracleId.as(() => HederaIdPropsFixture.create().value); + }, +); + export const CreateBondCommandFixture = createFixture( (command) => { command.security.fromFixture(SecurityPropsFixture); @@ -571,3 +580,10 @@ export const RedeemAtMaturityByPartitionRequestFixture = request.sourceId.as(() => HederaIdPropsFixture.create().value); request.partitionId.as(() => PartitionIdFixture.create().value); }); + +export const SetKpiOracleRequestFixture = createFixture( + (request) => { + request.securityId.as(() => HederaIdPropsFixture.create().value); + request.kpiOracleId.as(() => HederaIdPropsFixture.create().value); + }, +); diff --git a/packages/ats/sdk/__tests__/port/environmentMock.ts b/packages/ats/sdk/__tests__/port/environmentMock.ts index 40e5782f6..7d7344342 100644 --- a/packages/ats/sdk/__tests__/port/environmentMock.ts +++ b/packages/ats/sdk/__tests__/port/environmentMock.ts @@ -2241,6 +2241,7 @@ jest.mock('@port/out/rpc/RPCTransactionAdapter', () => { bondInfo.nominalValue, bondInfo.startingDate, _maturityDate, + bondInfo.kpiOracle, ); return { status: 'success', data: [] } as TransactionResponse< diff --git a/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommand.ts b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommand.ts new file mode 100644 index 000000000..b85249f5b --- /dev/null +++ b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommand.ts @@ -0,0 +1,223 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +import { Command } from '@core/command/Command'; +import { CommandResponse } from '@core/command/CommandResponse'; + +export class SetKpiOracleCommandResponse implements CommandResponse { + constructor( + public readonly payload: boolean, + public readonly transactionId: string, + ) {} +} + +export class SetKpiOracleCommand extends Command { + constructor( + public readonly securityId: string, + public readonly kpiOracleId: string, + ) { + super(); + } +} diff --git a/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommandHandler.ts b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommandHandler.ts new file mode 100644 index 000000000..96f6b2ea7 --- /dev/null +++ b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommandHandler.ts @@ -0,0 +1,269 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +import { ICommandHandler } from '@core/command/CommandHandler'; +import { CommandHandler } from '@core/decorator/CommandHandlerDecorator'; +import { + SetKpiOracleCommand, + SetKpiOracleCommandResponse, +} from './SetKpiOracleCommand'; +import TransactionService from '@service/transaction/TransactionService'; +import { lazyInject } from '@core/decorator/LazyInjectDecorator'; +import ContractService from '@service/contract/ContractService'; +import { SetKpiOracleCommandError } from './error/SetKpiOracleCommandError'; +import ValidationService from '@service/validation/ValidationService'; +import { SecurityRole } from '@domain/context/security/SecurityRole'; +import AccountService from '@service/account/AccountService'; + +@CommandHandler(SetKpiOracleCommand) +export class SetKpiOracleCommandHandler + implements ICommandHandler +{ + constructor( + @lazyInject(TransactionService) + private readonly transactionService: TransactionService, + @lazyInject(ContractService) + private readonly contractService: ContractService, + @lazyInject(ValidationService) + private readonly validationService: ValidationService, + @lazyInject(AccountService) + private readonly accountService: AccountService, + ) {} + + async execute( + command: SetKpiOracleCommand, + ): Promise { + try { + const { securityId, kpiOracleId } = command; + + const handler = this.transactionService.getHandler(); + + const account = this.accountService.getCurrentAccount(); + + const securityEvmAddress = + await this.contractService.getContractEvmAddress(securityId); + const kpiOracleEvmAddress = + await this.contractService.getContractEvmAddress(kpiOracleId); + + await this.validationService.checkRole( + SecurityRole._IR_CALCULATOR_MANAGER_ROLE, + account.id.toString(), + securityId, + ); + + const res = await handler.setKpiOracle( + securityEvmAddress, + kpiOracleEvmAddress, + securityId, + ); + + return Promise.resolve( + new SetKpiOracleCommandResponse(res.error == undefined, res.id!), + ); + } catch (error) { + throw new SetKpiOracleCommandError(error as Error); + } + } +} diff --git a/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommandHandler.unit.test.ts b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommandHandler.unit.test.ts new file mode 100644 index 000000000..a74f84ac7 --- /dev/null +++ b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/SetKpiOracleCommandHandler.unit.test.ts @@ -0,0 +1,319 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +import { + SetKpiOracleCommand, + SetKpiOracleCommandResponse, +} from './SetKpiOracleCommand'; +import { SetKpiOracleCommandHandler } from './SetKpiOracleCommandHandler'; +import { SetKpiOracleCommandFixture } from '@test/fixtures/bond/BondFixture'; +import { createMock } from '@golevelup/ts-jest'; +import TransactionService from '@service/transaction/TransactionService'; +import { + AccountPropsFixture, + ErrorMsgFixture, + EvmAddressPropsFixture, + TransactionIdFixture, +} from '@test/fixtures/shared/DataFixture'; +import ContractService from '@service/contract/ContractService'; +import EvmAddress from '@domain/context/contract/EvmAddress'; +import { ErrorCode } from '@core/error/BaseError'; +import { SetKpiOracleCommandError } from './error/SetKpiOracleCommandError'; +import ValidationService from '@service/validation/ValidationService'; +import AccountService from '@service/account/AccountService'; +import Account from '@domain/context/account/Account'; +import { SecurityRole } from '@domain/context/security/SecurityRole'; + +describe('SetKpiOracleCommandHandler', () => { + let handler: SetKpiOracleCommandHandler; + let command: SetKpiOracleCommand; + const transactionServiceMock = createMock(); + const contractServiceMock = createMock(); + const validationServiceMock = createMock(); + const accountServiceMock = createMock(); + + const evmAddress = new EvmAddress(EvmAddressPropsFixture.create().value); + const transactionId = TransactionIdFixture.create().id; + const account = new Account(AccountPropsFixture.create()); + const errorMsg = ErrorMsgFixture.create().msg; + + beforeEach(() => { + handler = new SetKpiOracleCommandHandler( + transactionServiceMock, + contractServiceMock, + validationServiceMock, + accountServiceMock, + ); + command = SetKpiOracleCommandFixture.create(); + }); + + afterEach(() => { + jest.resetAllMocks(); + }); + + describe('execute', () => { + describe('error cases', () => { + it('throws SetKpiOracleCommandError when command fails with uncaught error', async () => { + const fakeError = new Error(errorMsg); + + contractServiceMock.getContractEvmAddress.mockRejectedValue(fakeError); + + const resultPromise = handler.execute(command); + + await expect(resultPromise).rejects.toBeInstanceOf( + SetKpiOracleCommandError, + ); + + await expect(resultPromise).rejects.toMatchObject({ + message: expect.stringContaining( + `An error occurred while setting the KPI oracle: ${errorMsg}`, + ), + errorCode: ErrorCode.UncaughtCommandError, + }); + }); + }); + describe('success cases', () => { + it('should successfully set KPI oracle', async () => { + contractServiceMock.getContractEvmAddress.mockResolvedValue(evmAddress); + accountServiceMock.getCurrentAccount.mockReturnValue(account); + + transactionServiceMock.getHandler().setKpiOracle.mockResolvedValue({ + id: transactionId, + }); + + const result = await handler.execute(command); + + expect(result).toBeInstanceOf(SetKpiOracleCommandResponse); + expect(result.payload).toBe(true); + expect(result.transactionId).toBe(transactionId); + + expect(contractServiceMock.getContractEvmAddress).toHaveBeenCalledTimes( + 2, + ); + expect(contractServiceMock.getContractEvmAddress).toHaveBeenCalledWith( + command.securityId, + ); + expect(contractServiceMock.getContractEvmAddress).toHaveBeenCalledWith( + command.kpiOracleId, + ); + + expect( + transactionServiceMock.getHandler().setKpiOracle, + ).toHaveBeenCalledTimes(1); + + expect(validationServiceMock.checkRole).toHaveBeenCalledTimes(1); + expect(validationServiceMock.checkRole).toHaveBeenCalledWith( + SecurityRole._IR_CALCULATOR_MANAGER_ROLE, + account.id.toString(), + command.securityId, + ); + + expect( + transactionServiceMock.getHandler().setKpiOracle, + ).toHaveBeenCalledWith(evmAddress, evmAddress, command.securityId); + }); + }); + }); +}); diff --git a/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/error/SetKpiOracleCommandError.ts b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/error/SetKpiOracleCommandError.ts new file mode 100644 index 000000000..e84a44900 --- /dev/null +++ b/packages/ats/sdk/src/app/usecase/command/bond/coupon/kpiOracle/error/SetKpiOracleCommandError.ts @@ -0,0 +1,214 @@ +/* + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +*/ + +import { CommandError } from '@command/error/CommandError'; +import BaseError from '@core/error/BaseError'; + +export class SetKpiOracleCommandError extends CommandError { + constructor(error: Error) { + const msg = `An error occurred while setting the KPI oracle: ${error.message}`; + super(msg, error instanceof BaseError ? error.errorCode : undefined); + } +} diff --git a/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommand.ts b/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommand.ts index 01226d830..1d268aa21 100644 --- a/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommand.ts +++ b/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommand.ts @@ -238,6 +238,7 @@ export class CreateBondCommand extends Command { public readonly externalKycLists?: string[], public readonly compliance?: string, public readonly identityRegistry?: string, + public readonly kpiOracleId?: string, ) { super(); } diff --git a/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommandHandler.ts b/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommandHandler.ts index 739398a2a..6208f5167 100644 --- a/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommandHandler.ts +++ b/packages/ats/sdk/src/app/usecase/command/bond/create/CreateBondCommandHandler.ts @@ -266,6 +266,7 @@ export class CreateBondCommandHandler externalKycLists, compliance, identityRegistry, + kpiOracleId, } = command; //TODO: Boy scout: remove request validations and adjust test @@ -317,6 +318,9 @@ export class CreateBondCommandHandler const identityRegistryAddress = identityRegistry ? await this.contractService.getContractEvmAddress(identityRegistry) : new EvmAddress(EVM_ZERO_ADDRESS); + const kpiOracleEvmAddress = kpiOracleId + ? await this.contractService.getContractEvmAddress(kpiOracleId) + : new EvmAddress(EVM_ZERO_ADDRESS); const handler = this.transactionService.getHandler(); @@ -325,6 +329,7 @@ export class CreateBondCommandHandler BigDecimal.fromString(nominalValue), parseInt(startingDate), parseInt(maturityDate), + kpiOracleEvmAddress.toString(), ); const couponInfo = new CouponDetails( diff --git a/packages/ats/sdk/src/core/Constants.ts b/packages/ats/sdk/src/core/Constants.ts index 7ff1349f2..dfeca4858 100644 --- a/packages/ats/sdk/src/core/Constants.ts +++ b/packages/ats/sdk/src/core/Constants.ts @@ -347,6 +347,7 @@ export const GAS = { ADD_AGENT: 7000000, REMOVE_AGENT: 7000000, REDEEM_AT_MATURITY_BY_PARTITION_GAS: 700000, + SET_KPI_ORACLE_GAS: 700000, } as const; export const _PARTITION_ID_1 = diff --git a/packages/ats/sdk/src/domain/context/bond/BondDetails.ts b/packages/ats/sdk/src/domain/context/bond/BondDetails.ts index 9d6ebad82..58fd6b56b 100644 --- a/packages/ats/sdk/src/domain/context/bond/BondDetails.ts +++ b/packages/ats/sdk/src/domain/context/bond/BondDetails.ts @@ -212,12 +212,14 @@ export class BondDetails extends ValidatedDomain { nominalValue: BigDecimal; startingDate: number; maturityDate: number; + kpiOracle: string; constructor( currency: string, nominalValue: BigDecimal, startingDate: number, maturityDate: number, + kpiOracle: string, ) { super({ maturityDate: (val) => { @@ -229,6 +231,7 @@ export class BondDetails extends ValidatedDomain { this.nominalValue = nominalValue; this.startingDate = startingDate; this.maturityDate = maturityDate; + this.kpiOracle = kpiOracle; ValidatedDomain.handleValidation(BondDetails.name, this); } diff --git a/packages/ats/sdk/src/domain/context/factory/BondDetailsData.ts b/packages/ats/sdk/src/domain/context/factory/BondDetailsData.ts index 04e2ac1ea..7cefa27d0 100644 --- a/packages/ats/sdk/src/domain/context/factory/BondDetailsData.ts +++ b/packages/ats/sdk/src/domain/context/factory/BondDetailsData.ts @@ -211,12 +211,14 @@ export class BondDetailsData extends ValidatedDomain { public nominalValue: string; public startingDate: string; public maturityDate: string; + public kpiOracle: string; constructor( currency: string, nominalValue: string, startingDate: string, maturityDate: string, + kpiOracle: string, ) { super({ maturityDate: (val) => { @@ -231,6 +233,7 @@ export class BondDetailsData extends ValidatedDomain { this.nominalValue = nominalValue; this.startingDate = startingDate; this.maturityDate = maturityDate; + this.kpiOracle = kpiOracle; ValidatedDomain.handleValidation(BondDetailsData.name, this); } diff --git a/packages/ats/sdk/src/domain/context/security/SecurityRole.ts b/packages/ats/sdk/src/domain/context/security/SecurityRole.ts index c501884d4..b05720af2 100644 --- a/packages/ats/sdk/src/domain/context/security/SecurityRole.ts +++ b/packages/ats/sdk/src/domain/context/security/SecurityRole.ts @@ -234,6 +234,7 @@ export enum SecurityRole { _AGENT_ROLE = '0xc4aed0454da9bde6defa5baf93bb49d4690626fc243d138104e12d1def783ea6', _TREX_OWNER_ROLE = '0x03ce2fdc316501dd97f5219e6ad908a3238f1e90f910aa17b627f801a6aafab7', _MATURITY_REDEEMER_ROLE = '0xa0d696902e9ed231892dc96649f0c62b808a1cb9dd1269e78e0adc1cc4b8358c', + _IR_CALCULATOR_MANAGER_ROLE = '0xd24534fb8cd19dfb6a428826fa37cc6e73ee8e15a4610140722ad20fa3f0980d', } export function getProtectedPartitionRole(partitionId: string): string { diff --git a/packages/ats/sdk/src/domain/context/util/SecurityDataBuilder.ts b/packages/ats/sdk/src/domain/context/util/SecurityDataBuilder.ts index c2876c667..63215cb1a 100644 --- a/packages/ats/sdk/src/domain/context/util/SecurityDataBuilder.ts +++ b/packages/ats/sdk/src/domain/context/util/SecurityDataBuilder.ts @@ -297,6 +297,7 @@ export class SecurityDataBuilder { bondInfo.nominalValue.toString(), bondInfo.startingDate.toString(), bondInfo.maturityDate.toString(), + bondInfo.kpiOracle.toString(), ); } diff --git a/packages/ats/sdk/src/port/in/bond/Bond.ts b/packages/ats/sdk/src/port/in/bond/Bond.ts index c3a84e79e..a1794b560 100644 --- a/packages/ats/sdk/src/port/in/bond/Bond.ts +++ b/packages/ats/sdk/src/port/in/bond/Bond.ts @@ -248,6 +248,8 @@ import { } from '../request'; import { GetCouponHoldersQuery } from '@query/bond/coupons/getCouponHolders/GetCouponHoldersQuery'; import { GetTotalCouponHoldersQuery } from '@query/bond/coupons/getTotalCouponHolders/GetTotalCouponHoldersQuery'; +import SetKpiOracleRequest from '../request/bond/SetKpiOracleRequest'; +import { SetKpiOracleCommand } from '@command/bond/coupon/kpiOracle/SetKpiOracleCommand'; interface IBondInPort { create( @@ -271,6 +273,9 @@ interface IBondInPort { ): Promise<{ payload: boolean; transactionId: string }>; getCouponHolders(request: GetCouponHoldersRequest): Promise; getTotalCouponHolders(request: GetTotalCouponHoldersRequest): Promise; + setKpiOracle( + request: SetKpiOracleRequest, + ): Promise<{ payload: boolean; transactionId: string }>; } class BondInPort implements IBondInPort { @@ -516,6 +521,18 @@ class BondInPort implements IBondInPort { ); } + @LogError + async setKpiOracle( + request: SetKpiOracleRequest, + ): Promise<{ payload: boolean; transactionId: string }> { + const { securityId, kpiOracleId } = request; + ValidatedRequest.handleValidation(SetKpiOracleRequest.name, request); + + return await this.commandBus.execute( + new SetKpiOracleCommand(securityId, kpiOracleId), + ); + } + @LogError async getCouponHolders(request: GetCouponHoldersRequest): Promise { const { securityId, couponId, start, end } = request; diff --git a/packages/ats/sdk/src/port/in/bond/Bond.unit.test.ts b/packages/ats/sdk/src/port/in/bond/Bond.unit.test.ts index b2cd4f99e..d94dcba1c 100644 --- a/packages/ats/sdk/src/port/in/bond/Bond.unit.test.ts +++ b/packages/ats/sdk/src/port/in/bond/Bond.unit.test.ts @@ -243,6 +243,7 @@ import { GetTotalCouponHoldersRequestFixture, SetCouponRequestFixture, UpdateMaturityDateRequestFixture, + SetKpiOracleRequestFixture, } from '@test/fixtures/bond/BondFixture'; import { SecurityPropsFixture } from '@test/fixtures/shared/SecurityFixture'; import { Security } from '@domain/context/security/Security'; @@ -266,6 +267,8 @@ import { UpdateMaturityDateCommand } from '@command/bond/updateMaturityDate/Upda import { RedeemAtMaturityByPartitionCommand } from '@command/bond/redeemAtMaturityByPartition/RedeemAtMaturityByPartitionCommand'; import { GetCouponHoldersQuery } from '@query/bond/coupons/getCouponHolders/GetCouponHoldersQuery'; import { GetTotalCouponHoldersQuery } from '@query/bond/coupons/getTotalCouponHolders/GetTotalCouponHoldersQuery'; +import SetKpiOracleRequest from '../request/bond/SetKpiOracleRequest'; +import { SetKpiOracleCommand } from '@command/bond/coupon/kpiOracle/SetKpiOracleCommand'; describe('Bond', () => { let commandBusMock: jest.Mocked; @@ -281,6 +284,7 @@ describe('Bond', () => { let getAllCouponsRequest: GetAllCouponsRequest; let updateMaturityDateRequest: UpdateMaturityDateRequest; let redeemAtMaturityByPartitionRequest: RedeemAtMaturityByPartitionRequest; + let setKpiOracleRequest: SetKpiOracleRequest; let getCouponHoldersRequest: GetCouponHoldersRequest; let getTotalCouponHoldersRequest: GetTotalCouponHoldersRequest; @@ -1373,6 +1377,81 @@ describe('Bond', () => { }); }); + describe('setKpiOracle', () => { + setKpiOracleRequest = new SetKpiOracleRequest( + SetKpiOracleRequestFixture.create(), + ); + it('should set KPI oracle successfully', async () => { + const expectedResponse = { + payload: true, + transactionId: transactionId, + }; + + commandBusMock.execute.mockResolvedValue(expectedResponse); + + const result = await BondToken.setKpiOracle(setKpiOracleRequest); + + expect(handleValidationSpy).toHaveBeenCalledWith( + SetKpiOracleRequest.name, + setKpiOracleRequest, + ); + + expect(commandBusMock.execute).toHaveBeenCalledTimes(1); + + expect(commandBusMock.execute).toHaveBeenCalledWith( + new SetKpiOracleCommand( + setKpiOracleRequest.securityId, + setKpiOracleRequest.kpiOracleId, + ), + ); + + expect(result).toEqual(expectedResponse); + }); + + it('should throw an error if command execution fails', async () => { + const error = new Error('Command execution failed'); + commandBusMock.execute.mockRejectedValue(error); + + await expect(BondToken.setKpiOracle(setKpiOracleRequest)).rejects.toThrow( + 'Command execution failed', + ); + + expect(handleValidationSpy).toHaveBeenCalledWith( + SetKpiOracleRequest.name, + setKpiOracleRequest, + ); + + expect(commandBusMock.execute).toHaveBeenCalledWith( + new SetKpiOracleCommand( + setKpiOracleRequest.securityId, + setKpiOracleRequest.kpiOracleId, + ), + ); + }); + + it('should throw error if securityId is invalid', async () => { + setKpiOracleRequest = new SetKpiOracleRequest({ + ...SetKpiOracleRequestFixture.create(), + securityId: 'invalid', + }); + + await expect(BondToken.setKpiOracle(setKpiOracleRequest)).rejects.toThrow( + ValidationError, + ); + }); + + it('should throw error if kpiOracleId is invalid', async () => { + setKpiOracleRequest = new SetKpiOracleRequest({ + ...SetKpiOracleRequestFixture.create(), + kpiOracleId: 'invalid', + }); + + await expect(BondToken.setKpiOracle(setKpiOracleRequest)).rejects.toThrow( + ValidationError, + ); + }); + }); + describe('getCouponHolders', () => { getCouponHoldersRequest = new GetCouponHoldersRequest( GetCouponHoldersQueryFixture.create(), diff --git a/packages/ats/sdk/src/port/in/request/bond/CreateBondRequest.ts b/packages/ats/sdk/src/port/in/request/bond/CreateBondRequest.ts index 2c0ecdc9e..abdb5c212 100644 --- a/packages/ats/sdk/src/port/in/request/bond/CreateBondRequest.ts +++ b/packages/ats/sdk/src/port/in/request/bond/CreateBondRequest.ts @@ -247,6 +247,9 @@ export default class CreateBondRequest extends ValidatedRequest { @@ -402,6 +407,7 @@ export default class CreateBondRequest extends ValidatedRequest { + securityId: string; + kpiOracleId: string; + + constructor({ + securityId, + kpiOracleId, + }: { + securityId: string; + kpiOracleId: string; + }) { + super({ + securityId: FormatValidation.checkHederaIdFormatOrEvmAddress(), + kpiOracleId: FormatValidation.checkHederaIdFormatOrEvmAddress(true), + }); + + this.securityId = securityId; + this.kpiOracleId = kpiOracleId; + } +} diff --git a/packages/ats/sdk/src/port/out/TransactionAdapter.ts b/packages/ats/sdk/src/port/out/TransactionAdapter.ts index 3bc017cc1..cc8451129 100644 --- a/packages/ats/sdk/src/port/out/TransactionAdapter.ts +++ b/packages/ats/sdk/src/port/out/TransactionAdapter.ts @@ -513,6 +513,11 @@ interface ITransactionAdapter { amount: BigDecimal, securityId?: ContractId | string, ): Promise; + setKpiOracle( + security: EvmAddress, + kpiOracleId: EvmAddress, + securityId?: ContractId | string, + ): Promise; } interface RoleTransactionAdapter { @@ -1837,4 +1842,9 @@ export default abstract class TransactionAdapter amount: BigDecimal, securityId?: ContractId | string, ): Promise; + abstract setKpiOracle( + security: EvmAddress, + kpiOracleId: EvmAddress, + securityId?: ContractId | string, + ): Promise; } diff --git a/packages/ats/sdk/src/port/out/hs/HederaTransactionAdapter.ts b/packages/ats/sdk/src/port/out/hs/HederaTransactionAdapter.ts index b99acdccd..f8c81bb57 100644 --- a/packages/ats/sdk/src/port/out/hs/HederaTransactionAdapter.ts +++ b/packages/ats/sdk/src/port/out/hs/HederaTransactionAdapter.ts @@ -604,6 +604,7 @@ export abstract class HederaTransactionAdapter extends TransactionAdapter { bondInfo.nominalValue.toString(), bondInfo.startingDate.toString(), bondInfo.maturityDate.toString(), + bondInfo.kpiOracle ); const couponDetails: CouponDetailsData = { @@ -3156,6 +3157,24 @@ export abstract class HederaTransactionAdapter extends TransactionAdapter { ); } + async setKpiOracle( + security: EvmAddress, + kpiOracleId: EvmAddress, + securityId: ContractId | string, + ): Promise { + LogService.logTrace( + `Setting KPI oracle to ${kpiOracleId.toString()}`, + ); + const contract = new Contract(security.toString(), Bond__factory.abi); + return this.executeWithArgs( + contract, + 'setKpiOracle', + securityId, + GAS.SET_KPI_ORACLE_GAS, + [security.toString(), kpiOracleId.toString()], + ); + } + // * Definition of the abstract methods abstract signAndSendTransaction( transaction: Transaction, diff --git a/packages/ats/sdk/src/port/out/rpc/RPCQueryAdapter.ts b/packages/ats/sdk/src/port/out/rpc/RPCQueryAdapter.ts index 39c8e437d..f2f6425b1 100644 --- a/packages/ats/sdk/src/port/out/rpc/RPCQueryAdapter.ts +++ b/packages/ats/sdk/src/port/out/rpc/RPCQueryAdapter.ts @@ -679,6 +679,7 @@ export class RPCQueryAdapter { new BigDecimal(res.nominalValue.toString()), res.startingDate.toNumber(), res.maturityDate.toNumber(), + res.kpiOracle ); } diff --git a/packages/ats/sdk/src/port/out/rpc/RPCTransactionAdapter.ts b/packages/ats/sdk/src/port/out/rpc/RPCTransactionAdapter.ts index 7da823a72..8052e6767 100644 --- a/packages/ats/sdk/src/port/out/rpc/RPCTransactionAdapter.ts +++ b/packages/ats/sdk/src/port/out/rpc/RPCTransactionAdapter.ts @@ -3000,6 +3000,22 @@ export class RPCTransactionAdapter extends TransactionAdapter { ); } + async setKpiOracle( + securityId: EvmAddress, + kpiOracleId: EvmAddress, + ): Promise { + LogService.logTrace( + `Setting KPI oracle to ${kpiOracleId.toString()}`, + ); + + return this.executeTransaction( + Bond__factory.connect(securityId.toString(), this.getSignerOrProvider()), + 'setKpiOracle', + [securityId.toString(), kpiOracleId.toString()], + GAS.SET_KPI_ORACLE_GAS, + ); + } + private async executeTransaction( factory: any, method: string,