diff --git a/packages/actus-solidity/contracts/Core/Utils/CycleUtils.sol b/packages/actus-solidity/contracts/Core/Utils/CycleUtils.sol index a1ba0dd5..941c3a4a 100644 --- a/packages/actus-solidity/contracts/Core/Utils/CycleUtils.sol +++ b/packages/actus-solidity/contracts/Core/Utils/CycleUtils.sol @@ -47,14 +47,13 @@ contract CycleUtils is ACTUSConstants, PeriodUtils { } /** - * This function computes an array of UNIX timestamps that - * represent dates in a cycle falling within a given segment. + * Computes an array of timestamps that represent dates in a cycle falling within a given segment. * @dev There are some notable edge cases: If the cycle is "not set" we return the start end end dates * of the cycle if they lie within the segment. Otherwise and empty array is returned. - * @param cycleStart the start time of the cycle - * @param cycleEnd the end time of the cycle - * @param cycle struct that describe sthe cycle - * @param addEndTime specifies if the timestamp of the end of the cycle should be added to the result if it falls in the segment + * @param cycleStart start time of the cycle + * @param cycleEnd end time of the cycle + * @param cycle IPS cycle + * @param addEndTime timestamp of the end of the cycle should be added to the result if it falls in the segment * @param segmentStart start time of the segment * @param segmentEnd end time of the segment * @return an array of timestamps from the given cycle that fall within the specified segement @@ -102,9 +101,7 @@ contract CycleUtils is ACTUSConstants, PeriodUtils { cycleIndex++; - date = getNextCycleDate(cycle, cycleStart, cycleIndex); - } // add additional time at the end if addEndTime @@ -126,6 +123,27 @@ contract CycleUtils is ACTUSConstants, PeriodUtils { } /** + * Computes the next date for a given an IPS cycle. + * @param cycle IPS cycle + * @param precedingDate the previous date of the cycle + * @return next date of the cycle + */ + function computeNextCycleDateFromPrecedingDate( + IPS memory cycle, + uint256 precedingDate + ) + internal + pure + returns (uint256) + { + if (cycle.isSet == false) { + return 0; + } + + return getNextCycleDate(cycle, precedingDate, 1); + } + + /* * @notice Checks if a timestamp is in a given range. */ function isInSegment( diff --git a/packages/actus-solidity/contracts/Engines/ANN/ANNEngine.sol b/packages/actus-solidity/contracts/Engines/ANN/ANNEngine.sol index 89bd6d6f..2c5078b4 100755 --- a/packages/actus-solidity/contracts/Engines/ANN/ANNEngine.sol +++ b/packages/actus-solidity/contracts/Engines/ANN/ANNEngine.sol @@ -286,6 +286,82 @@ contract ANNEngine is Core, ANNSTF, ANNPOF, IANNEngine { return schedule; } + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + ANNTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + override + returns(bytes32) + { + // IP + if (eventType == EventType.IP) { + // interest payment related (starting with PRANX interest is paid following the PR schedule) + if ( + terms.cycleOfInterestPayment.isSet == true && terms.cycleAnchorDateOfInterestPayment != 0) { + uint256 nextInterestPaymentDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfInterestPayment, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfInterestPayment : lastScheduleTime + ); + if (nextInterestPaymentDate == 0) return bytes32(0); + if (nextInterestPaymentDate <= terms.capitalizationEndDate) return bytes32(0); + return encodeEvent(EventType.IP, nextInterestPaymentDate); + } + } + + // IPCI + if (eventType == EventType.IPCI) { + if ( + terms.cycleOfInterestPayment.isSet == true + && terms.cycleAnchorDateOfInterestPayment != 0 + && terms.capitalizationEndDate != 0 + ) { + IPS memory cycleOfInterestCapitalization = terms.cycleOfInterestPayment; + cycleOfInterestCapitalization.s = S.SHORT; + uint256 nextInterestCapitalizationDate = computeNextCycleDateFromPrecedingDate( + cycleOfInterestCapitalization, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfInterestPayment : lastScheduleTime + ); + if (nextInterestCapitalizationDate == 0) return bytes32(0); + return encodeEvent(EventType.IPCI, nextInterestCapitalizationDate); + } + } + + // fees + if (eventType == EventType.FP) { + if (terms.cycleOfFee.isSet == true && terms.cycleAnchorDateOfFee != 0) { + uint256 nextFeeDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfFee, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfFee : lastScheduleTime + ); + if (nextFeeDate == 0) return bytes32(0); + return encodeEvent(EventType.FP, nextFeeDate); + } + } + + // principal redemption + if (eventType == EventType.PR) { + uint256 nextPrincipalRedemptionDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfPrincipalRedemption, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfPrincipalRedemption : lastScheduleTime + ); + if (nextPrincipalRedemptionDate == 0) return bytes32(0); + return encodeEvent(EventType.PR, nextPrincipalRedemptionDate); + } + + return bytes32(0); + } + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/contracts/Engines/ANN/IANNEngine.sol b/packages/actus-solidity/contracts/Engines/ANN/IANNEngine.sol index dff86728..bdd42dfa 100755 --- a/packages/actus-solidity/contracts/Engines/ANN/IANNEngine.sol +++ b/packages/actus-solidity/contracts/Engines/ANN/IANNEngine.sol @@ -75,6 +75,23 @@ interface IANNEngine is IEngine { pure returns (bytes32[] memory); + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + ANNTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + returns(bytes32); + /** * @notice Computes a schedule segment of cyclic contract events based on the contract terms * and the specified timestamps. diff --git a/packages/actus-solidity/contracts/Engines/CEC/CECEngine.sol b/packages/actus-solidity/contracts/Engines/CEC/CECEngine.sol index 73751076..a4f0ac79 100644 --- a/packages/actus-solidity/contracts/Engines/CEC/CECEngine.sol +++ b/packages/actus-solidity/contracts/Engines/CEC/CECEngine.sol @@ -166,6 +166,27 @@ contract CECEngine is Core, CECSTF, CECPOF, ICECEngine { return schedule; } + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + CECTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + override + returns(bytes32) + { + return bytes32(0); + } + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/contracts/Engines/CEC/ICECEngine.sol b/packages/actus-solidity/contracts/Engines/CEC/ICECEngine.sol index 056a2d0b..8993619b 100755 --- a/packages/actus-solidity/contracts/Engines/CEC/ICECEngine.sol +++ b/packages/actus-solidity/contracts/Engines/CEC/ICECEngine.sol @@ -94,6 +94,23 @@ interface ICECEngine is IEngine { pure returns (bytes32[] memory); + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + CECTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + returns(bytes32); + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/contracts/Engines/CEG/CEGEngine.sol b/packages/actus-solidity/contracts/Engines/CEG/CEGEngine.sol index 783c5d73..f0e5cf5f 100644 --- a/packages/actus-solidity/contracts/Engines/CEG/CEGEngine.sol +++ b/packages/actus-solidity/contracts/Engines/CEG/CEGEngine.sol @@ -202,6 +202,39 @@ contract CEGEngine is Core, CEGSTF, CEGPOF, ICEGEngine { return schedule; } + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + CEGTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + override + returns(bytes32) + { + if (eventType == EventType.FP) { + // fees + if (terms.cycleOfFee.isSet == true && terms.cycleAnchorDateOfFee != 0) { + uint256 nextFeeDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfFee, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfFee : lastScheduleTime + ); + if (nextFeeDate == 0) return bytes32(0); + return encodeEvent(EventType.FP, nextFeeDate); + } + } + + return bytes32(0); + } + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/contracts/Engines/CEG/ICEGEngine.sol b/packages/actus-solidity/contracts/Engines/CEG/ICEGEngine.sol index c3ddb7f0..841c19e6 100755 --- a/packages/actus-solidity/contracts/Engines/CEG/ICEGEngine.sol +++ b/packages/actus-solidity/contracts/Engines/CEG/ICEGEngine.sol @@ -94,6 +94,23 @@ interface ICEGEngine is IEngine { pure returns (bytes32[] memory); + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + CEGTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + returns(bytes32); + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/contracts/Engines/CERTF/CERTFEngine.sol b/packages/actus-solidity/contracts/Engines/CERTF/CERTFEngine.sol index 9c69a66a..d7229f28 100755 --- a/packages/actus-solidity/contracts/Engines/CERTF/CERTFEngine.sol +++ b/packages/actus-solidity/contracts/Engines/CERTF/CERTFEngine.sol @@ -294,6 +294,86 @@ contract CERTFEngine is Core, CERTFSTF, CERTFPOF, ICERTFEngine { return schedule; } + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + CERTFTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + override + returns(bytes32) + { + if (eventType == EventType.CFD) { + if (terms.cycleOfCoupon.isSet == true && terms.cycleAnchorDateOfCoupon != 0) { + uint256 nextCouponDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfCoupon, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfCoupon : lastScheduleTime + ); + if (nextCouponDate == uint256(0)) return bytes32(0); + return encodeEvent(EventType.CFD, nextCouponDate); + } + } + + if (eventType == EventType.CPD) { + if (terms.cycleOfCoupon.isSet == true && terms.cycleAnchorDateOfCoupon != 0) { + uint256 nextCouponDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfCoupon, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfCoupon : lastScheduleTime + ); + if (nextCouponDate == uint256(0)) return bytes32(0); + uint256 couponPaymentDayScheduleTime = getTimestampPlusPeriod(terms.settlementPeriod, nextCouponDate); + return encodeEvent(EventType.CFD, couponPaymentDayScheduleTime); + } + } + + if (eventType == EventType.RFD) { + if (terms.cycleOfRedemption.isSet == true && terms.cycleAnchorDateOfRedemption != 0) { + uint256 nextRedemptionDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfRedemption, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfRedemption : lastScheduleTime + ); + if (nextRedemptionDate == uint256(0)) return bytes32(0); + return encodeEvent(EventType.RFD, nextRedemptionDate); + } + } + + if (eventType == EventType.RPD) { + if (terms.cycleOfRedemption.isSet == true && terms.cycleAnchorDateOfRedemption != 0) { + uint256 nextRedemptionDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfRedemption, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfRedemption : lastScheduleTime + ); + if (nextRedemptionDate == uint256(0)) return bytes32(0); + uint256 redemptionPaymentDayScheduleTime = getTimestampPlusPeriod(terms.settlementPeriod, nextRedemptionDate); + return encodeEvent(EventType.RPD, redemptionPaymentDayScheduleTime); + } + } + + if (eventType == EventType.XD) { + if (terms.cycleOfRedemption.isSet == true && terms.cycleAnchorDateOfRedemption != 0) { + uint256 nextRedemptionDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfRedemption, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfRedemption : lastScheduleTime + ); + if (nextRedemptionDate == uint256(0)) return bytes32(0); + if (nextRedemptionDate == terms.maturityDate) return bytes32(0); + uint256 executionDateScheduleTime = getTimestampPlusPeriod(terms.exercisePeriod, nextRedemptionDate); + return encodeEvent(EventType.XD, executionDateScheduleTime); + } + } + + return bytes32(0); + } + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/contracts/Engines/CERTF/ICERTFEngine.sol b/packages/actus-solidity/contracts/Engines/CERTF/ICERTFEngine.sol index a4b87486..ca962e6d 100755 --- a/packages/actus-solidity/contracts/Engines/CERTF/ICERTFEngine.sol +++ b/packages/actus-solidity/contracts/Engines/CERTF/ICERTFEngine.sol @@ -94,6 +94,23 @@ interface ICERTFEngine is IEngine { pure returns (bytes32[] memory); + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + CERTFTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + returns(bytes32); + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/contracts/Engines/PAM/IPAMEngine.sol b/packages/actus-solidity/contracts/Engines/PAM/IPAMEngine.sol index 43ad204c..c9130878 100755 --- a/packages/actus-solidity/contracts/Engines/PAM/IPAMEngine.sol +++ b/packages/actus-solidity/contracts/Engines/PAM/IPAMEngine.sol @@ -75,6 +75,23 @@ interface IPAMEngine is IEngine { pure returns (bytes32[] memory); + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + PAMTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + returns(bytes32); + /** * @notice Computes a schedule segment of cyclic contract events based on the contract terms * and the specified timestamps. diff --git a/packages/actus-solidity/contracts/Engines/PAM/PAMEngine.sol b/packages/actus-solidity/contracts/Engines/PAM/PAMEngine.sol index 080ff426..18d8be78 100755 --- a/packages/actus-solidity/contracts/Engines/PAM/PAMEngine.sol +++ b/packages/actus-solidity/contracts/Engines/PAM/PAMEngine.sol @@ -183,8 +183,7 @@ contract PAMEngine is Core, PAMSTF, PAMPOF, IPAMEngine { uint256 index; if (eventType == EventType.IP) { - // interest payment related (covers pre-repayment period only, - // starting with PRANX interest is paid following the PR schedule) + // interest payment related (starting with PRANX interest is paid following the PR schedule) if ( terms.cycleOfInterestPayment.isSet == true && terms.cycleAnchorDateOfInterestPayment != 0 @@ -306,6 +305,96 @@ contract PAMEngine is Core, PAMSTF, PAMPOF, IPAMEngine { return schedule; } + /** + * @notice Computes a schedule segment of cyclic contract events based on the contract terms + * and the specified timestamps. + * @param terms terms of the contract + * @param lastScheduleTime last occurrence of cyclic event + * @param eventType eventType of the cyclic schedule + * @return event schedule segment + */ + function computeNextCyclicEvent( + PAMTerms calldata terms, + uint256 lastScheduleTime, + EventType eventType + ) + external + pure + override + returns(bytes32) + { + if (eventType == EventType.IP) { + // interest payment related (starting with PRANX interest is paid following the PR schedule) + if ( + terms.cycleOfInterestPayment.isSet == true && terms.cycleAnchorDateOfInterestPayment != 0) { + uint256 nextInterestPaymentDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfInterestPayment, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfInterestPayment : lastScheduleTime + ); + if (nextInterestPaymentDate == 0) return bytes32(0); + if (nextInterestPaymentDate <= terms.capitalizationEndDate) return bytes32(0); + return encodeEvent(EventType.IP, nextInterestPaymentDate); + } + } + + if (eventType == EventType.IPCI) { + // IPCI + if ( + terms.cycleOfInterestPayment.isSet == true + && terms.cycleAnchorDateOfInterestPayment != 0 + && terms.capitalizationEndDate != 0 + ) { + IPS memory cycleOfInterestCapitalization = terms.cycleOfInterestPayment; + cycleOfInterestCapitalization.s = S.SHORT; + uint256 nextInterestCapitalizationDate = computeNextCycleDateFromPrecedingDate( + cycleOfInterestCapitalization, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfInterestPayment : lastScheduleTime + ); + if (nextInterestCapitalizationDate == 0) return bytes32(0); + return encodeEvent(EventType.IPCI, nextInterestCapitalizationDate); + } + } + + if (eventType == EventType.RR) { + // rate reset + if (terms.cycleOfRateReset.isSet == true && terms.cycleAnchorDateOfRateReset != 0) { + uint256 nextRateResetDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfRateReset, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfRateReset : lastScheduleTime + ); + if (nextRateResetDate == 0) return bytes32(0); + return encodeEvent(EventType.RR, nextRateResetDate); + } + // ... nextRateReset + } + + if (eventType == EventType.FP) { + // fees + if (terms.cycleOfFee.isSet == true && terms.cycleAnchorDateOfFee != 0) { + uint256 nextFeeDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfFee, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfFee : lastScheduleTime + ); + if (nextFeeDate == 0) return bytes32(0); + return encodeEvent(EventType.FP, nextFeeDate); + } + } + + if (eventType == EventType.SC) { + // scaling + if ((terms.scalingEffect != ScalingEffect._000) && terms.cycleAnchorDateOfScalingIndex != 0) { + uint256 nextScalingDate = computeNextCycleDateFromPrecedingDate( + terms.cycleOfScalingIndex, + (lastScheduleTime == 0) ? terms.cycleAnchorDateOfScalingIndex : lastScheduleTime + ); + if (nextScalingDate == 0) return bytes32(0); + return encodeEvent(EventType.SC, nextScalingDate); + } + } + + return bytes32(0); + } + /** * @notice Verifies that the provided event is still scheduled under the terms, the current state of the * contract and the current state of the underlying. diff --git a/packages/actus-solidity/package.json b/packages/actus-solidity/package.json index 112cc4d0..1b7b7ab4 100644 --- a/packages/actus-solidity/package.json +++ b/packages/actus-solidity/package.json @@ -32,7 +32,7 @@ ], "scripts": { "build": "npm run compile && npm run generate-artifacts", - "compile": "truffle compile", + "compile": "node --max-old-space-size=4096 ./node_modules/.bin/truffle compile", "coverage": "node --max-old-space-size=4096 ./node_modules/.bin/buidler coverage", "generate-artifacts": "rm -rf ./artifacts && ./scripts/truffle-minimize.sh ./build/contracts ./artifacts", "generate-docs": "./scripts/generate-docs.sh", diff --git a/packages/ap-contracts/contracts/Core/ANN/ANNEncoder.sol b/packages/ap-contracts/contracts/Core/ANN/ANNEncoder.sol index 350c1cc2..9f6b4c8f 100644 --- a/packages/ap-contracts/contracts/Core/ANN/ANNEncoder.sol +++ b/packages/ap-contracts/contracts/Core/ANN/ANNEncoder.sol @@ -1,5 +1,6 @@ // "SPDX-License-Identifier: Apache-2.0" pragma solidity ^0.6.10; +pragma experimental ABIEncoderV2; import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistryStorage.sol"; @@ -18,7 +19,7 @@ library ANNEncoder { * @notice All non zero values of the overwrittenTerms object are stored. * It does not check if overwrittenAttributesMap actually marks attribute as overwritten. */ - function encodeAndSetANNTerms(Asset storage asset, ANNTerms memory terms) internal { + function encodeAndSetANNTerms(Asset storage asset, ANNTerms memory terms) external { storeInPackedTerms( asset, "enums", @@ -128,7 +129,7 @@ library ANNEncoder { /** * @dev Decode and loads ANNTerms */ - function decodeAndGetANNTerms(Asset storage asset) internal view returns (ANNTerms memory) { + function decodeAndGetANNTerms(Asset storage asset) external view returns (ANNTerms memory) { return ANNTerms( ContractType(uint8(uint256(asset.packedTerms["enums"] >> 248))), Calendar(uint8(uint256(asset.packedTerms["enums"] >> 240))), @@ -220,7 +221,7 @@ library ANNEncoder { } function decodeAndGetEnumValueForANNAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint8) { @@ -248,7 +249,7 @@ library ANNEncoder { } function decodeAndGetAddressValueForForANNAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (address) { @@ -262,7 +263,7 @@ library ANNEncoder { } function decodeAndGetBytes32ValueForForANNAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (bytes32) { @@ -270,7 +271,7 @@ library ANNEncoder { } function decodeAndGetUIntValueForForANNAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint256) { @@ -278,7 +279,7 @@ library ANNEncoder { } function decodeAndGetIntValueForForANNAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (int256) { @@ -286,7 +287,7 @@ library ANNEncoder { } function decodeAndGetPeriodValueForForANNAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IP memory) { @@ -305,7 +306,7 @@ library ANNEncoder { } function decodeAndGetCycleValueForForANNAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IPS memory) { @@ -328,7 +329,7 @@ library ANNEncoder { } function decodeAndGetContractReferenceValueForANNAttribute(Asset storage /* asset */, bytes32 /* attributeKey */) - internal + external pure returns (ContractReference memory) { diff --git a/packages/ap-contracts/contracts/Core/ANN/ANNRegistry.sol b/packages/ap-contracts/contracts/Core/ANN/ANNRegistry.sol index 265b711e..61401d32 100644 --- a/packages/ap-contracts/contracts/Core/ANN/ANNRegistry.sol +++ b/packages/ap-contracts/contracts/Core/ANN/ANNRegistry.sol @@ -2,6 +2,8 @@ pragma solidity ^0.6.10; pragma experimental ABIEncoderV2; +import "@atpar/actus-solidity/contracts/Engines/ANN/IANNEngine.sol"; + import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistry.sol"; import "./ANNEncoder.sol"; @@ -150,4 +152,91 @@ contract ANNRegistry is BaseRegistry, IANNRegistry { { return assets[assetId].decodeAndGetContractReferenceValueForANNAttribute(attribute); } + + function getNextCyclicEvent(bytes32 assetId) + internal + view + override(TermsRegistry) + returns (bytes32) + { + Asset storage asset = assets[assetId]; + ANNTerms memory terms = asset.decodeAndGetANNTerms(); + + EventType nextEventType; + uint256 nextScheduleTimeOffset; + + // IP + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IANNEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.IP], + EventType.IP + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset < nextScheduleTimeOffset) + || (nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // IPCI + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IANNEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.IPCI], + EventType.IPCI + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // FP + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IANNEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.FP], + EventType.FP + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // PR + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IANNEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.PR], + EventType.PR + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + return encodeEvent(nextEventType, nextScheduleTimeOffset); + } } diff --git a/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Schedule/ScheduleRegistry.sol b/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Schedule/ScheduleRegistry.sol index d77424a7..d8b03305 100644 --- a/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Schedule/ScheduleRegistry.sol +++ b/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Schedule/ScheduleRegistry.sol @@ -27,10 +27,6 @@ abstract contract ScheduleRegistry is EventUtils, PeriodUtils { - - event IncrementedScheduleIndex(bytes32 indexed assetId, uint256 nextScheduleIndex); - - /** * @notice Returns an event for a given position (index) in a schedule of a given asset. * @param assetId id of the asset @@ -154,7 +150,7 @@ abstract contract ScheduleRegistry is // solium-disable-next-line block.timestamp ); - } + } // if not check if performance of underlying asset is covered by this asset (PF excluded) if ( creditEventTypeCovered != ContractPerformance.PF @@ -198,10 +194,22 @@ abstract contract ScheduleRegistry is returns (bytes32) { Asset storage asset = assets[assetId]; + bytes32 nextCyclicEvent = getNextCyclicEvent(assetId); + bytes32 nextScheduleEvent = asset.schedule.events[asset.schedule.nextScheduleIndex]; - if (asset.schedule.length == 0) return bytes32(0); - - return asset.schedule.events[asset.schedule.nextScheduleIndex]; + if (asset.schedule.length == 0 && nextCyclicEvent == bytes32(0)) return bytes32(0); + + (, uint256 scheduleTimeNextCyclicEvent) = decodeEvent(nextCyclicEvent); + (, uint256 scheduleTimeNextScheduleEvent) = decodeEvent(nextScheduleEvent); + + if ( + scheduleTimeNextScheduleEvent == 0 + || (scheduleTimeNextCyclicEvent != 0 && scheduleTimeNextCyclicEvent < scheduleTimeNextScheduleEvent) + ) { + return nextCyclicEvent; + } else { + return nextScheduleEvent; + } } /** @@ -217,15 +225,40 @@ abstract contract ScheduleRegistry is returns (bytes32) { Asset storage asset = assets[assetId]; + bytes32 nextCyclicEvent = getNextCyclicEvent(assetId); + bytes32 nextScheduleEvent = asset.schedule.events[asset.schedule.nextScheduleIndex]; - if (asset.schedule.nextScheduleIndex == asset.schedule.length) return bytes32(0); + if (asset.schedule.length == 0 && nextCyclicEvent == bytes32(0)) return bytes32(0); - bytes32 _event = asset.schedule.events[asset.schedule.nextScheduleIndex]; - asset.schedule.nextScheduleIndex += 1; - - emit IncrementedScheduleIndex(assetId, asset.schedule.nextScheduleIndex); + (EventType eventTypeNextCyclicEvent, uint256 scheduleTimeNextCyclicEvent) = decodeEvent(nextCyclicEvent); + (EventType eventTypeNextScheduleEvent, uint256 scheduleTimeNextScheduleEvent) = decodeEvent(nextScheduleEvent); - return _event; + // update both next cyclic event and next schedule event if they are the same + if (nextCyclicEvent == nextScheduleEvent) { + asset.schedule.lastScheduleTimeOfCyclicEvent[eventTypeNextCyclicEvent] = scheduleTimeNextCyclicEvent; + if (asset.schedule.nextScheduleIndex == asset.schedule.length) return bytes32(0); + asset.schedule.nextScheduleIndex += 1; + // does matter since they are the same + return nextCyclicEvent; + } + + // next cyclic event occurs earlier than next schedule event + if ( + (scheduleTimeNextScheduleEvent == 0 || (scheduleTimeNextCyclicEvent != 0 && scheduleTimeNextCyclicEvent < scheduleTimeNextScheduleEvent)) + || ( + scheduleTimeNextCyclicEvent == scheduleTimeNextScheduleEvent + && getEpochOffset(eventTypeNextCyclicEvent) < getEpochOffset(eventTypeNextScheduleEvent) + ) + ) { + asset.schedule.lastScheduleTimeOfCyclicEvent[eventTypeNextCyclicEvent] = scheduleTimeNextCyclicEvent; + return nextCyclicEvent; + } else { + if (scheduleTimeNextScheduleEvent == 0 || asset.schedule.nextScheduleIndex == asset.schedule.length) { + return bytes32(0); + } + asset.schedule.nextScheduleIndex += 1; + return nextScheduleEvent; + } } /** @@ -258,5 +291,16 @@ abstract contract ScheduleRegistry is isAuthorized (assetId) { assets[assetId].settlement[_event] = Settlement({ isSettled: true, payoff: _payoff }); - } + } + + // function decodeEvent(bytes32 _event) + // internal + // pure + // returns (EventType, uint256) + // { + // EventType eventType = EventType(uint8(uint256(_event >> 248))); + // uint256 scheduleTime = uint256(uint64(uint256(_event))); + + // return (eventType, scheduleTime); + // } } diff --git a/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Terms/TermsRegistry.sol b/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Terms/TermsRegistry.sol index 3114bfc2..00b3f7a7 100644 --- a/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Terms/TermsRegistry.sol +++ b/packages/ap-contracts/contracts/Core/Base/AssetRegistry/Terms/TermsRegistry.sol @@ -57,4 +57,10 @@ abstract contract TermsRegistry { view virtual returns (ContractReference memory); + + function getNextCyclicEvent(bytes32 assetId) + internal + view + virtual + returns (bytes32); } diff --git a/packages/ap-contracts/contracts/Core/Base/SharedTypes.sol b/packages/ap-contracts/contracts/Core/Base/SharedTypes.sol index 40580cce..9a624c0c 100644 --- a/packages/ap-contracts/contracts/Core/Base/SharedTypes.sol +++ b/packages/ap-contracts/contracts/Core/Base/SharedTypes.sol @@ -18,7 +18,8 @@ struct AssetOwnership { struct Schedule { // scheduleTime and EventType are tighlty packed and encoded as bytes32 - + // ... + mapping(EventType => uint256) lastScheduleTimeOfCyclicEvent; // index of event => bytes32 encoded event mapping(uint256 => bytes32) events; // the length of the schedule, used to determine the end of the schedule @@ -28,5 +29,3 @@ struct Schedule { // last event which could not be settled bytes32 pendingEvent; } - -// contract SharedTypes is ACTUSConstants {} diff --git a/packages/ap-contracts/contracts/Core/CEC/CECEncoder.sol b/packages/ap-contracts/contracts/Core/CEC/CECEncoder.sol index f0c472c3..9a002ee2 100644 --- a/packages/ap-contracts/contracts/Core/CEC/CECEncoder.sol +++ b/packages/ap-contracts/contracts/Core/CEC/CECEncoder.sol @@ -1,5 +1,6 @@ // "SPDX-License-Identifier: Apache-2.0" pragma solidity ^0.6.10; +pragma experimental ABIEncoderV2; import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistryStorage.sol"; @@ -18,7 +19,7 @@ library CECEncoder { * @notice All non zero values of the overwrittenTerms object are stored. * It does not check if overwrittenAttributesMap actually marks attribute as overwritten. */ - function encodeAndSetCECTerms(Asset storage asset, CECTerms memory terms) internal { + function encodeAndSetCECTerms(Asset storage asset, CECTerms memory terms) external { storeInPackedTerms( asset, "enums", @@ -80,7 +81,7 @@ library CECEncoder { /** * @dev Decode and loads CECTerms */ - function decodeAndGetCECTerms(Asset storage asset) internal view returns (CECTerms memory) { + function decodeAndGetCECTerms(Asset storage asset) external view returns (CECTerms memory) { return CECTerms( ContractType(uint8(uint256(asset.packedTerms["enums"] >> 248))), Calendar(uint8(uint256(asset.packedTerms["enums"] >> 240))), @@ -114,7 +115,7 @@ library CECEncoder { } function decodeAndGetEnumValueForCECAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint8) { @@ -140,7 +141,7 @@ library CECEncoder { } function decodeAndGetAddressValueForForCECAttribute(Asset storage /* asset */, bytes32 /* attributeKey */) - internal + external pure returns (address) { @@ -148,7 +149,7 @@ library CECEncoder { } function decodeAndGetBytes32ValueForForCECAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (bytes32) { @@ -156,7 +157,7 @@ library CECEncoder { } function decodeAndGetUIntValueForForCECAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint256) { @@ -164,7 +165,7 @@ library CECEncoder { } function decodeAndGetIntValueForForCECAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (int256) { @@ -172,7 +173,7 @@ library CECEncoder { } function decodeAndGetPeriodValueForForCECAttribute(Asset storage /* asset */, bytes32 /* attributeKey */) - internal + external pure returns (IP memory) { @@ -180,7 +181,7 @@ library CECEncoder { } function decodeAndGetCycleValueForForCECAttribute(Asset storage /* asset */, bytes32 /* attributeKey */) - internal + external pure returns (IPS memory) { @@ -188,7 +189,7 @@ library CECEncoder { } function decodeAndGetContractReferenceValueForCECAttribute(Asset storage asset , bytes32 attributeKey ) - internal + external view returns (ContractReference memory) { diff --git a/packages/ap-contracts/contracts/Core/CEC/CECRegistry.sol b/packages/ap-contracts/contracts/Core/CEC/CECRegistry.sol index db1cf628..726e43db 100644 --- a/packages/ap-contracts/contracts/Core/CEC/CECRegistry.sol +++ b/packages/ap-contracts/contracts/Core/CEC/CECRegistry.sol @@ -150,4 +150,13 @@ contract CECRegistry is BaseRegistry, ICECRegistry { { return assets[assetId].decodeAndGetContractReferenceValueForCECAttribute(attribute); } + + function getNextCyclicEvent(bytes32 assetId) + internal + view + override(TermsRegistry) + returns (bytes32) + { + return bytes32(0); + } } diff --git a/packages/ap-contracts/contracts/Core/CEG/CEGEncoder.sol b/packages/ap-contracts/contracts/Core/CEG/CEGEncoder.sol index 60d115f9..8c512a52 100644 --- a/packages/ap-contracts/contracts/Core/CEG/CEGEncoder.sol +++ b/packages/ap-contracts/contracts/Core/CEG/CEGEncoder.sol @@ -1,5 +1,6 @@ // "SPDX-License-Identifier: Apache-2.0" pragma solidity ^0.6.10; +pragma experimental ABIEncoderV2; import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistryStorage.sol"; @@ -18,7 +19,7 @@ library CEGEncoder { * @notice All non zero values of the overwrittenTerms object are stored. * It does not check if overwrittenAttributesMap actually marks attribute as overwritten. */ - function encodeAndSetCEGTerms(Asset storage asset, CEGTerms memory terms) internal { + function encodeAndSetCEGTerms(Asset storage asset, CEGTerms memory terms) external { storeInPackedTerms( asset, "enums", @@ -114,7 +115,7 @@ library CEGEncoder { /** * @dev Decode and loads CEGTerms */ - function decodeAndGetCEGTerms(Asset storage asset) internal view returns (CEGTerms memory) { + function decodeAndGetCEGTerms(Asset storage asset) external view returns (CEGTerms memory) { return CEGTerms( ContractType(uint8(uint256(asset.packedTerms["enums"] >> 248))), Calendar(uint8(uint256(asset.packedTerms["enums"] >> 240))), @@ -177,7 +178,7 @@ library CEGEncoder { } function decodeAndGetEnumValueForCEGAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint8) { @@ -203,7 +204,7 @@ library CEGEncoder { } function decodeAndGetAddressValueForForCEGAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (address) { @@ -217,7 +218,7 @@ library CEGEncoder { } function decodeAndGetBytes32ValueForForCEGAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (bytes32) { @@ -225,7 +226,7 @@ library CEGEncoder { } function decodeAndGetUIntValueForForCEGAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint256) { @@ -233,7 +234,7 @@ library CEGEncoder { } function decodeAndGetIntValueForForCEGAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (int256) { @@ -241,7 +242,7 @@ library CEGEncoder { } function decodeAndGetPeriodValueForForCEGAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IP memory) { @@ -260,7 +261,7 @@ library CEGEncoder { } function decodeAndGetCycleValueForForCEGAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IPS memory) { @@ -279,7 +280,7 @@ library CEGEncoder { } function decodeAndGetContractReferenceValueForCEGAttribute(Asset storage asset , bytes32 attributeKey ) - internal + external view returns (ContractReference memory) { diff --git a/packages/ap-contracts/contracts/Core/CEG/CEGRegistry.sol b/packages/ap-contracts/contracts/Core/CEG/CEGRegistry.sol index 9e53d359..756c4569 100644 --- a/packages/ap-contracts/contracts/Core/CEG/CEGRegistry.sol +++ b/packages/ap-contracts/contracts/Core/CEG/CEGRegistry.sol @@ -2,6 +2,8 @@ pragma solidity ^0.6.10; pragma experimental ABIEncoderV2; +import "@atpar/actus-solidity/contracts/Engines/CEG/ICEGEngine.sol"; + import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistry.sol"; import "./CEGEncoder.sol"; @@ -150,4 +152,37 @@ contract CEGRegistry is BaseRegistry, ICEGRegistry { { return assets[assetId].decodeAndGetContractReferenceValueForCEGAttribute(attribute); } + + function getNextCyclicEvent(bytes32 assetId) + internal + view + override(TermsRegistry) + returns (bytes32) + { + Asset storage asset = assets[assetId]; + CEGTerms memory terms = asset.decodeAndGetCEGTerms(); + + EventType nextEventType; + uint256 nextScheduleTimeOffset; + + // FP + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(ICEGEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.FP], + EventType.FP + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset < nextScheduleTimeOffset) + || (nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + return encodeEvent(nextEventType, nextScheduleTimeOffset); + } } diff --git a/packages/ap-contracts/contracts/Core/CERTF/CERTFEncoder.sol b/packages/ap-contracts/contracts/Core/CERTF/CERTFEncoder.sol index 4665fe1e..ee63acce 100644 --- a/packages/ap-contracts/contracts/Core/CERTF/CERTFEncoder.sol +++ b/packages/ap-contracts/contracts/Core/CERTF/CERTFEncoder.sol @@ -1,5 +1,6 @@ // "SPDX-License-Identifier: Apache-2.0" pragma solidity ^0.6.10; +pragma experimental ABIEncoderV2; import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistryStorage.sol"; @@ -18,7 +19,7 @@ library CERTFEncoder { * @notice All non zero values of the overwrittenTerms object are stored. * It does not check if overwrittenAttributesMap actually marks attribute as overwritten. */ - function encodeAndSetCERTFTerms(Asset storage asset, CERTFTerms memory terms) internal { + function encodeAndSetCERTFTerms(Asset storage asset, CERTFTerms memory terms) external { storeInPackedTerms( asset, "enums", @@ -134,7 +135,7 @@ library CERTFEncoder { /** * @dev Decode and loads CERTFTerms */ - function decodeAndGetCERTFTerms(Asset storage asset) internal view returns (CERTFTerms memory) { + function decodeAndGetCERTFTerms(Asset storage asset) external view returns (CERTFTerms memory) { return CERTFTerms( ContractType(uint8(uint256(asset.packedTerms["enums"] >> 248))), Calendar(uint8(uint256(asset.packedTerms["enums"] >> 240))), @@ -217,7 +218,7 @@ library CERTFEncoder { } function decodeAndGetEnumValueForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint8) { @@ -243,7 +244,7 @@ library CERTFEncoder { } function decodeAndGetAddressValueForForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (address) { @@ -257,7 +258,7 @@ library CERTFEncoder { } function decodeAndGetBytes32ValueForForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (bytes32) { @@ -265,7 +266,7 @@ library CERTFEncoder { } function decodeAndGetUIntValueForForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint256) { @@ -273,7 +274,7 @@ library CERTFEncoder { } function decodeAndGetIntValueForForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (int256) { @@ -281,7 +282,7 @@ library CERTFEncoder { } function decodeAndGetPeriodValueForForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IP memory) { @@ -303,7 +304,7 @@ library CERTFEncoder { } function decodeAndGetCycleValueForForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IPS memory) { @@ -324,7 +325,7 @@ library CERTFEncoder { } function decodeAndGetContractReferenceValueForCERTFAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (ContractReference memory) { diff --git a/packages/ap-contracts/contracts/Core/CERTF/CERTFRegistry.sol b/packages/ap-contracts/contracts/Core/CERTF/CERTFRegistry.sol index e0fc96b3..e10fe2a2 100644 --- a/packages/ap-contracts/contracts/Core/CERTF/CERTFRegistry.sol +++ b/packages/ap-contracts/contracts/Core/CERTF/CERTFRegistry.sol @@ -2,6 +2,8 @@ pragma solidity ^0.6.10; pragma experimental ABIEncoderV2; +import "@atpar/actus-solidity/contracts/Engines/CERTF/ICERTFEngine.sol"; + import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistry.sol"; import "./CERTFEncoder.sol"; @@ -150,4 +152,109 @@ contract CERTFRegistry is BaseRegistry, ICERTFRegistry { { return assets[assetId].decodeAndGetContractReferenceValueForCERTFAttribute(attribute); } + + function getNextCyclicEvent(bytes32 assetId) + internal + view + override(TermsRegistry) + returns (bytes32) + { + Asset storage asset = assets[assetId]; + CERTFTerms memory terms = asset.decodeAndGetCERTFTerms(); + + EventType nextEventType; + uint256 nextScheduleTimeOffset; + + // CFD + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(ICERTFEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.CFD], + EventType.CFD + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset < nextScheduleTimeOffset) + || (nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // CPD + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(ICERTFEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.CPD], + EventType.CPD + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // RFD + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(ICERTFEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.RFD], + EventType.RFD + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // RPD + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(ICERTFEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.RPD], + EventType.RPD + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // XD + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(ICERTFEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.XD], + EventType.XD + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + return encodeEvent(nextEventType, nextScheduleTimeOffset); + } } diff --git a/packages/ap-contracts/contracts/Core/PAM/PAMEncoder.sol b/packages/ap-contracts/contracts/Core/PAM/PAMEncoder.sol index 12d5030c..6a8190ea 100644 --- a/packages/ap-contracts/contracts/Core/PAM/PAMEncoder.sol +++ b/packages/ap-contracts/contracts/Core/PAM/PAMEncoder.sol @@ -1,5 +1,6 @@ // "SPDX-License-Identifier: Apache-2.0" pragma solidity ^0.6.10; +pragma experimental ABIEncoderV2; import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistryStorage.sol"; @@ -18,7 +19,7 @@ library PAMEncoder { * @notice All non zero values of the overwrittenTerms object are stored. * It does not check if overwrittenAttributesMap actually marks attribute as overwritten. */ - function encodeAndSetPAMTerms(Asset storage asset, PAMTerms memory terms) internal { + function encodeAndSetPAMTerms(Asset storage asset, PAMTerms memory terms) external { storeInPackedTerms( asset, "enums", @@ -118,7 +119,7 @@ library PAMEncoder { /** * @dev Decode and loads PAMTerms */ - function decodeAndGetPAMTerms(Asset storage asset) internal view returns (PAMTerms memory) { + function decodeAndGetPAMTerms(Asset storage asset) external view returns (PAMTerms memory) { return PAMTerms( ContractType(uint8(uint256(asset.packedTerms["enums"] >> 248))), Calendar(uint8(uint256(asset.packedTerms["enums"] >> 240))), @@ -202,7 +203,7 @@ library PAMEncoder { } function decodeAndGetEnumValueForPAMAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint8) { @@ -230,7 +231,7 @@ library PAMEncoder { } function decodeAndGetAddressValueForForPAMAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (address) { @@ -244,7 +245,7 @@ library PAMEncoder { } function decodeAndGetBytes32ValueForForPAMAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (bytes32) { @@ -252,7 +253,7 @@ library PAMEncoder { } function decodeAndGetUIntValueForForPAMAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (uint256) { @@ -260,7 +261,7 @@ library PAMEncoder { } function decodeAndGetIntValueForForPAMAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (int256) { @@ -268,7 +269,7 @@ library PAMEncoder { } function decodeAndGetPeriodValueForForPAMAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IP memory) { @@ -287,7 +288,7 @@ library PAMEncoder { } function decodeAndGetCycleValueForForPAMAttribute(Asset storage asset, bytes32 attributeKey) - internal + external view returns (IPS memory) { @@ -309,7 +310,7 @@ library PAMEncoder { } function decodeAndGetContractReferenceValueForPAMAttribute(Asset storage /* asset */, bytes32 /* attributeKey */) - internal + external pure returns (ContractReference memory) { diff --git a/packages/ap-contracts/contracts/Core/PAM/PAMRegistry.sol b/packages/ap-contracts/contracts/Core/PAM/PAMRegistry.sol index c91cd06b..88147b1b 100644 --- a/packages/ap-contracts/contracts/Core/PAM/PAMRegistry.sol +++ b/packages/ap-contracts/contracts/Core/PAM/PAMRegistry.sol @@ -2,6 +2,8 @@ pragma solidity ^0.6.10; pragma experimental ABIEncoderV2; +import "@atpar/actus-solidity/contracts/Engines/PAM/IPAMEngine.sol"; + import "../Base/SharedTypes.sol"; import "../Base/AssetRegistry/BaseRegistry.sol"; import "./PAMEncoder.sol"; @@ -150,4 +152,91 @@ contract PAMRegistry is BaseRegistry, IPAMRegistry { { return assets[assetId].decodeAndGetContractReferenceValueForPAMAttribute(attribute); } + + function getNextCyclicEvent(bytes32 assetId) + internal + view + override(TermsRegistry) + returns (bytes32) + { + Asset storage asset = assets[assetId]; + PAMTerms memory terms = asset.decodeAndGetPAMTerms(); + + EventType nextEventType; + uint256 nextScheduleTimeOffset; + + // IP + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IPAMEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.IP], + EventType.IP + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset < nextScheduleTimeOffset) + || (nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // IPCI + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IPAMEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.IPCI], + EventType.IPCI + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // FP + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IPAMEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.FP], + EventType.FP + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + // SC + { + (EventType eventType, uint256 scheduleTimeOffset) = decodeEvent(IPAMEngine(asset.engine).computeNextCyclicEvent( + terms, + asset.schedule.lastScheduleTimeOfCyclicEvent[EventType.SC], + EventType.SC + )); + + if ( + (nextScheduleTimeOffset == 0) + || (scheduleTimeOffset != 0 && scheduleTimeOffset < nextScheduleTimeOffset) + || (scheduleTimeOffset != 0 && nextScheduleTimeOffset == scheduleTimeOffset && getEpochOffset(eventType) < getEpochOffset(nextEventType)) + ) { + nextScheduleTimeOffset = scheduleTimeOffset; + nextEventType = eventType; + } + } + + return encodeEvent(nextEventType, nextScheduleTimeOffset); + } } diff --git a/packages/ap-contracts/migrations/2_deploy_contracts.js b/packages/ap-contracts/migrations/2_deploy_contracts.js index 9d4c6d8f..7013dada 100755 --- a/packages/ap-contracts/migrations/2_deploy_contracts.js +++ b/packages/ap-contracts/migrations/2_deploy_contracts.js @@ -13,6 +13,12 @@ const CEGRegistry = artifacts.require('CEGRegistry'); const CERTFRegistry = artifacts.require('CERTFRegistry'); const PAMRegistry = artifacts.require('PAMRegistry'); +const ANNEncoder = artifacts.require('ANNEncoder'); +const CECEncoder = artifacts.require('CECEncoder'); +const CEGEncoder = artifacts.require('CEGEncoder'); +const CERTFEncoder = artifacts.require('CERTFEncoder'); +const PAMEncoder = artifacts.require('PAMEncoder'); + const ANNActor = artifacts.require('ANNActor'); const CECActor = artifacts.require('CECActor'); const CEGActor = artifacts.require('CEGActor'); @@ -36,6 +42,16 @@ module.exports = async (deployer, network) => { instances.PAMEngineInstance = await deployer.deploy(PAMEngine); // Asset Registry + await deployer.deploy(ANNEncoder); + await deployer.deploy(CECEncoder); + await deployer.deploy(CEGEncoder); + await deployer.deploy(CERTFEncoder); + await deployer.deploy(PAMEncoder); + deployer.link(ANNEncoder, ANNRegistry); + deployer.link(CECEncoder, CECRegistry); + deployer.link(CEGEncoder, CEGRegistry); + deployer.link(CERTFEncoder, CERTFRegistry); + deployer.link(PAMEncoder, PAMRegistry); instances.ANNRegistryInstance = await deployer.deploy(ANNRegistry); instances.CECRegistryInstance = await deployer.deploy(CECRegistry); instances.CEGRegistryInstance = await deployer.deploy(CEGRegistry); diff --git a/packages/ap-contracts/package.json b/packages/ap-contracts/package.json index 58f1e269..c38eac80 100644 --- a/packages/ap-contracts/package.json +++ b/packages/ap-contracts/package.json @@ -29,8 +29,8 @@ }, "scripts": { "build": "npm run compile:all && npm run generate-artifacts && npm run generate-ts-bindings", - "compile:all": "truffle compile --all", - "compile": "truffle compile", + "compile:all": "node --max-old-space-size=4096 ./node_modules/.bin/truffle compile --all", + "compile": "node --max-old-space-size=4096 ./node_modules/.bin/truffle compile", "coverage": "node --max-old-space-size=4096 ./node_modules/.bin/buidler coverage", "generate-artifacts": "rm -rf ./artifacts && ./scripts/truffle-minimize.sh ./build/contracts ./artifacts", "generate-docs": "./scripts/generate-docs.sh", diff --git a/packages/ap-contracts/test/Core/ANN/ANNActor/TestCycles.js b/packages/ap-contracts/test/Core/ANN/ANNActor/TestCycles.js new file mode 100644 index 00000000..b02c8190 --- /dev/null +++ b/packages/ap-contracts/test/Core/ANN/ANNActor/TestCycles.js @@ -0,0 +1,123 @@ +const BigNumber = require('bignumber.js'); +const { expectEvent } = require('openzeppelin-test-helpers'); + +const { setupTestEnvironment, getDefaultTerms, deployPaymentToken, parseToContractTerms } = require('../../../helper/setupTestEnvironment'); +const { createSnapshot, revertToSnapshot, mineBlock } = require('../../../helper/blockchain'); +const { generateSchedule, parseTerms, ZERO_ADDRESS, ZERO_BYTES32, web3ResponseToState } = require('../../../helper/utils'); + +const ANNActor = artifacts.require('ANNActor'); + + +contract('ANNActor', (accounts) => { + + const creatorObligor = accounts[1]; + const creatorBeneficiary = accounts[2]; + const counterpartyObligor = accounts[3]; + const counterpartyBeneficiary = accounts[4]; + + let snapshot; + let snapshot_asset; + + const getEventTime = async (_event, terms) => { + return Number(await this.ANNEngineInstance.computeEventTimeForEvent( + _event, + terms.businessDayConvention, + terms.calendar, + terms.maturityDate + )); + } + + before(async () => { + this.instances = await setupTestEnvironment(accounts); + Object.keys(this.instances).forEach((instance) => this[instance] = this.instances[instance]); + + this.ownership = { creatorObligor, creatorBeneficiary, counterpartyObligor, counterpartyBeneficiary }; + this.terms = { + ...await getDefaultTerms('ANN'), + gracePeriod: { i: 1, p: 2, isSet: true }, + delinquencyPeriod: { i: 1, p: 3, isSet: true } + }; + + // deploy test ERC20 token + this.PaymentTokenInstance = await deployPaymentToken(creatorObligor, [counterpartyObligor, counterpartyBeneficiary]); + + // set address of payment token as currency in terms + this.terms.currency = this.PaymentTokenInstance.address; + this.terms.settlementCurrency = this.PaymentTokenInstance.address; + this.terms.statusDate = this.terms.contractDealDate; + + this.schedule = []; + this.state = web3ResponseToState(await this.ANNEngineInstance.computeInitialState(this.terms)); + + const tx = await this.ANNActorInstance.initialize( + this.terms, + this.schedule, + this.ownership, + this.ANNEngineInstance.address, + ZERO_ADDRESS + ); + + await expectEvent.inTransaction( + tx.tx, ANNActor, 'InitializedAsset' + ); + + this.assetId = tx.logs[0].args.assetId; + + snapshot = await createSnapshot(); + }); + + after(async () => { + await revertToSnapshot(snapshot); + }); + + it('should process the next cyclic event', async () => { + const _event = await this.ANNRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); + const eventTime = await getEventTime(_event, this.terms) + + const payoff = new BigNumber(await this.ANNEngineInstance.computePayoffForEvent( + this.terms, + this.state, + _event, + web3.utils.toHex(eventTime) + )); + + const value = web3.utils.toHex((payoff.isGreaterThan(0)) ? payoff : payoff.negated()); + + // set allowance for Payment Router + await this.PaymentTokenInstance.approve( + this.ANNActorInstance.address, + value, + { from: (payoff.isGreaterThan(0)) ? counterpartyObligor : creatorObligor } + ); + + // settle and progress asset state + await mineBlock(eventTime); + const tx = await this.ANNActorInstance.progress( + web3.utils.toHex(this.assetId), + { from: creatorObligor } + ); + const { args: { 0: emittedAssetId } } = await expectEvent.inTransaction( + tx.tx, ANNActor, 'ProgressedAsset' + ); + + const storedNextState = web3ResponseToState(await this.ANNRegistryInstance.getState(web3.utils.toHex(this.assetId))); + const isEventSettled = await this.ANNRegistryInstance.isEventSettled(web3.utils.toHex(this.assetId), _event); + const projectedNextState = web3ResponseToState(await this.ANNEngineInstance.computeStateForEvent( + this.terms, + this.state, + _event, + web3.utils.toHex(0) + )); + const storedNextEvent = await this.ANNRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); + + assert.equal(emittedAssetId, this.assetId); + assert.notEqual(storedNextEvent, _event); + assert.equal(storedNextState.statusDate, eventTime); + assert.equal(isEventSettled[0], true); + assert.equal(isEventSettled[1].toString(), payoff.toFixed()); + assert.deepEqual(storedNextState, projectedNextState); + + await revertToSnapshot(snapshot_asset); + snapshot_asset = await createSnapshot(); + }); +}); diff --git a/packages/ap-contracts/test/Core/ANN/ANNActor/TestPerformance.js b/packages/ap-contracts/test/Core/ANN/ANNActor/TestPerformance.js index 086fcbbf..b041e332 100644 --- a/packages/ap-contracts/test/Core/ANN/ANNActor/TestPerformance.js +++ b/packages/ap-contracts/test/Core/ANN/ANNActor/TestPerformance.js @@ -33,7 +33,7 @@ contract('ANNActor', (accounts) => { this.ownership = { creatorObligor, creatorBeneficiary, counterpartyObligor, counterpartyBeneficiary }; this.terms = { - ...await getDefaultTerms("ANN"), + ...await getDefaultTerms('ANN'), gracePeriod: { i: 1, p: 2, isSet: true }, delinquencyPeriod: { i: 1, p: 3, isSet: true } }; diff --git a/packages/ap-contracts/test/Core/CEG/CEGActor/TestCycles.js b/packages/ap-contracts/test/Core/CEG/CEGActor/TestCycles.js new file mode 100644 index 00000000..e53b5ceb --- /dev/null +++ b/packages/ap-contracts/test/Core/CEG/CEGActor/TestCycles.js @@ -0,0 +1,123 @@ +// const BigNumber = require('bignumber.js'); +// const { expectEvent } = require('openzeppelin-test-helpers'); + +// const { setupTestEnvironment, getDefaultTerms, deployPaymentToken, parseToContractTerms } = require('../../../helper/setupTestEnvironment'); +// const { createSnapshot, revertToSnapshot, mineBlock } = require('../../../helper/blockchain'); +// const { generateSchedule, parseTerms, ZERO_ADDRESS, ZERO_BYTES32, web3ResponseToState } = require('../../../helper/utils'); + +// const CEGActor = artifacts.require('CEGActor'); + + +// contract('CEGActor', (accounts) => { + +// const creatorObligor = accounts[1]; +// const creatorBeneficiary = accounts[2]; +// const counterpartyObligor = accounts[3]; +// const counterpartyBeneficiary = accounts[4]; + +// let snapshot; +// let snapshot_asset; + +// const getEventTime = async (_event, terms) => { +// return Number(await this.CEGEngineInstance.computeEventTimeForEvent( +// _event, +// terms.businessDayConvention, +// terms.calendar, +// terms.maturityDate +// )); +// } + +// before(async () => { +// this.instances = await setupTestEnvironment(accounts); +// Object.keys(this.instances).forEach((instance) => this[instance] = this.instances[instance]); + +// this.ownership = { creatorObligor, creatorBeneficiary, counterpartyObligor, counterpartyBeneficiary }; +// this.terms = { +// ...await getDefaultTerms('CEG'), +// gracePeriod: { i: 1, p: 2, isSet: true }, +// delinquencyPeriod: { i: 1, p: 3, isSet: true } +// }; + +// // deploy test ERC20 token +// this.PaymentTokenInstance = await deployPaymentToken(creatorObligor, [counterpartyObligor, counterpartyBeneficiary]); + +// // set address of payment token as currency in terms +// this.terms.currency = this.PaymentTokenInstance.address; +// this.terms.settlementCurrency = this.PaymentTokenInstance.address; +// this.terms.statusDate = this.terms.contractDealDate; + +// this.schedule = []; +// this.state = web3ResponseToState(await this.CEGEngineInstance.computeInitialState(this.terms)); + +// const tx = await this.CEGActorInstance.initialize( +// this.terms, +// this.schedule, +// this.ownership, +// this.CEGEngineInstance.address, +// ZERO_ADDRESS +// ); + +// await expectEvent.inTransaction( +// tx.tx, CEGActor, 'InitializedAsset' +// ); + +// this.assetId = tx.logs[0].args.assetId; + +// snapshot = await createSnapshot(); +// }); + +// after(async () => { +// await revertToSnapshot(snapshot); +// }); + +// it('should process the next cyclic event', async () => { +// const _event = await this.ANNRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); +// const eventTime = await getEventTime(_event, this.terms) + +// const payoff = new BigNumber(await this.CEGEngineInstance.computePayoffForEvent( +// this.terms, +// this.state, +// _event, +// web3.utils.toHex(eventTime) +// )); + +// const value = web3.utils.toHex((payoff.isGreaterThan(0)) ? payoff : payoff.negated()); + +// // set allowance for Payment Router +// await this.PaymentTokenInstance.approve( +// this.CEGActorInstance.address, +// value, +// { from: (payoff.isGreaterThan(0)) ? counterpartyObligor : creatorObligor } +// ); + +// // settle and progress asset state +// await mineBlock(eventTime); +// const tx = await this.CEGActorInstance.progress( +// web3.utils.toHex(this.assetId), +// { from: creatorObligor } +// ); +// const { args: { 0: emittedAssetId } } = await expectEvent.inTransaction( +// tx.tx, CEGActor, 'ProgressedAsset' +// ); + +// const storedNextState = web3ResponseToState(await this.ANNRegistryInstance.getState(web3.utils.toHex(this.assetId))); +// const isEventSettled = await this.ANNRegistryInstance.isEventSettled(web3.utils.toHex(this.assetId), _event); +// const projectedNextState = web3ResponseToState(await this.CEGEngineInstance.computeStateForEvent( +// this.terms, +// this.state, +// _event, +// web3.utils.toHex(eventTime) +// )); +// const storedNextEvent = await this.ANNRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); + +// assert.equal(emittedAssetId, this.assetId); +// assert.notEqual(storedNextEvent, _event); +// assert.equal(storedNextState.statusDate, eventTime); +// assert.equal(isEventSettled[0], true); +// assert.equal(isEventSettled[1].toString(), payoff.toFixed()); +// assert.deepEqual(storedNextState, projectedNextState); + +// await revertToSnapshot(snapshot_asset); +// snapshot_asset = await createSnapshot(); +// }); +// }); diff --git a/packages/ap-contracts/test/Core/CERTF/CERTFActor/TestCycles.js b/packages/ap-contracts/test/Core/CERTF/CERTFActor/TestCycles.js new file mode 100644 index 00000000..0cb6f103 --- /dev/null +++ b/packages/ap-contracts/test/Core/CERTF/CERTFActor/TestCycles.js @@ -0,0 +1,123 @@ +const BigNumber = require('bignumber.js'); +const { expectEvent } = require('openzeppelin-test-helpers'); + +const { setupTestEnvironment, getDefaultTerms, deployPaymentToken, parseToContractTerms } = require('../../../helper/setupTestEnvironment'); +const { createSnapshot, revertToSnapshot, mineBlock } = require('../../../helper/blockchain'); +const { generateSchedule, parseTerms, ZERO_ADDRESS, ZERO_BYTES32, web3ResponseToState } = require('../../../helper/utils'); + +const CERTFActor = artifacts.require('CERTFActor'); + + +contract('CERTFActor', (accounts) => { + + const creatorObligor = accounts[1]; + const creatorBeneficiary = accounts[2]; + const counterpartyObligor = accounts[3]; + const counterpartyBeneficiary = accounts[4]; + + let snapshot; + let snapshot_asset; + + const getEventTime = async (_event, terms) => { + return Number(await this.CERTFEngineInstance.computeEventTimeForEvent( + _event, + terms.businessDayConvention, + terms.calendar, + terms.maturityDate + )); + } + + before(async () => { + this.instances = await setupTestEnvironment(accounts); + Object.keys(this.instances).forEach((instance) => this[instance] = this.instances[instance]); + + this.ownership = { creatorObligor, creatorBeneficiary, counterpartyObligor, counterpartyBeneficiary }; + this.terms = { + ...await getDefaultTerms('CERTF'), + gracePeriod: { i: 1, p: 2, isSet: true }, + delinquencyPeriod: { i: 1, p: 3, isSet: true } + }; + + // deploy test ERC20 token + this.PaymentTokenInstance = await deployPaymentToken(creatorObligor, [counterpartyObligor, counterpartyBeneficiary]); + + // set address of payment token as currency in terms + this.terms.currency = this.PaymentTokenInstance.address; + this.terms.settlementCurrency = this.PaymentTokenInstance.address; + this.terms.statusDate = this.terms.contractDealDate; + + this.schedule = []; + this.state = web3ResponseToState(await this.CERTFEngineInstance.computeInitialState(this.terms)); + + const tx = await this.CERTFActorInstance.initialize( + this.terms, + this.schedule, + this.ownership, + this.CERTFEngineInstance.address, + ZERO_ADDRESS + ); + + await expectEvent.inTransaction( + tx.tx, CERTFActor, 'InitializedAsset' + ); + + this.assetId = tx.logs[0].args.assetId; + + snapshot = await createSnapshot(); + }); + + after(async () => { + await revertToSnapshot(snapshot); + }); + + it('should process the next cyclic event', async () => { + const _event = await this.CERTFRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); + const eventTime = await getEventTime(_event, this.terms) + + const payoff = new BigNumber(await this.CERTFEngineInstance.computePayoffForEvent( + this.terms, + this.state, + _event, + web3.utils.toHex(eventTime) + )); + + const value = web3.utils.toHex((payoff.isGreaterThan(0)) ? payoff : payoff.negated()); + + // set allowance for Payment Router + await this.PaymentTokenInstance.approve( + this.CERTFActorInstance.address, + value, + { from: (payoff.isGreaterThan(0)) ? counterpartyObligor : creatorObligor } + ); + + // settle and progress asset state + await mineBlock(eventTime); + const tx = await this.CERTFActorInstance.progress( + web3.utils.toHex(this.assetId), + { from: creatorObligor } + ); + const { args: { 0: emittedAssetId } } = await expectEvent.inTransaction( + tx.tx, CERTFActor, 'ProgressedAsset' + ); + + const storedNextState = web3ResponseToState(await this.CERTFRegistryInstance.getState(web3.utils.toHex(this.assetId))); + const isEventSettled = await this.CERTFRegistryInstance.isEventSettled(web3.utils.toHex(this.assetId), _event); + const projectedNextState = web3ResponseToState(await this.CERTFEngineInstance.computeStateForEvent( + this.terms, + this.state, + _event, + web3.utils.toHex(0) + )); + const storedNextEvent = await this.CERTFRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); + + assert.equal(emittedAssetId, this.assetId); + assert.notEqual(storedNextEvent, _event); + assert.equal(storedNextState.statusDate, eventTime); + assert.equal(isEventSettled[0], true); + assert.equal(isEventSettled[1].toString(), payoff.toFixed()); + assert.deepEqual(storedNextState, projectedNextState); + + await revertToSnapshot(snapshot_asset); + snapshot_asset = await createSnapshot(); + }); +}); diff --git a/packages/ap-contracts/test/Core/PAM/PAMActor/TestCycles.js b/packages/ap-contracts/test/Core/PAM/PAMActor/TestCycles.js new file mode 100644 index 00000000..4e34afbe --- /dev/null +++ b/packages/ap-contracts/test/Core/PAM/PAMActor/TestCycles.js @@ -0,0 +1,124 @@ +const BigNumber = require('bignumber.js'); +const { expectEvent } = require('openzeppelin-test-helpers'); + +const { setupTestEnvironment, getDefaultTerms, deployPaymentToken, parseToContractTerms } = require('../../../helper/setupTestEnvironment'); +const { createSnapshot, revertToSnapshot, mineBlock } = require('../../../helper/blockchain'); +const { generateSchedule, parseTerms, ZERO_ADDRESS, ZERO_BYTES32, web3ResponseToState } = require('../../../helper/utils'); + +const PAMActor = artifacts.require('PAMActor'); + + +contract('PAMActor', (accounts) => { + + const creatorObligor = accounts[1]; + const creatorBeneficiary = accounts[2]; + const counterpartyObligor = accounts[3]; + const counterpartyBeneficiary = accounts[4]; + + let snapshot; + let snapshot_asset; + + const getEventTime = async (_event, terms) => { + return Number(await this.PAMEngineInstance.computeEventTimeForEvent( + _event, + terms.businessDayConvention, + terms.calendar, + terms.maturityDate + )); + } + + before(async () => { + this.instances = await setupTestEnvironment(accounts); + Object.keys(this.instances).forEach((instance) => this[instance] = this.instances[instance]); + + this.ownership = { creatorObligor, creatorBeneficiary, counterpartyObligor, counterpartyBeneficiary }; + this.terms = { + ...await getDefaultTerms('PAM'), + gracePeriod: { i: 1, p: 2, isSet: true }, + delinquencyPeriod: { i: 1, p: 3, isSet: true } + }; + + // deploy test ERC20 token + this.PaymentTokenInstance = await deployPaymentToken(creatorObligor, [counterpartyObligor, counterpartyBeneficiary]); + + // set address of payment token as currency in terms + this.terms.currency = this.PaymentTokenInstance.address; + this.terms.settlementCurrency = this.PaymentTokenInstance.address; + this.terms.statusDate = this.terms.contractDealDate; + + this.schedule = []; + this.state = web3ResponseToState(await this.PAMEngineInstance.computeInitialState(this.terms)); + + const tx = await this.PAMActorInstance.initialize( + this.terms, + this.schedule, + this.ownership, + this.PAMEngineInstance.address, + ZERO_ADDRESS + ); + + await expectEvent.inTransaction( + tx.tx, PAMActor, 'InitializedAsset' + ); + + this.assetId = tx.logs[0].args.assetId; + + snapshot = await createSnapshot(); + }); + + after(async () => { + await revertToSnapshot(snapshot); + }); + + it('should process the next cyclic event', async () => { + const _event = await this.PAMRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); + const eventTime = await getEventTime(_event, this.terms) + console.log(_event); + + const payoff = new BigNumber(await this.PAMEngineInstance.computePayoffForEvent( + this.terms, + this.state, + _event, + web3.utils.toHex(0) + )); + + const value = web3.utils.toHex((payoff.isGreaterThan(0)) ? payoff : payoff.negated()); + + // set allowance for Payment Router + await this.PaymentTokenInstance.approve( + this.PAMActorInstance.address, + value, + { from: (payoff.isGreaterThan(0)) ? counterpartyObligor : creatorObligor } + ); + + // settle and progress asset state + await mineBlock(eventTime); + const tx = await this.PAMActorInstance.progress( + web3.utils.toHex(this.assetId), + { from: creatorObligor } + ); + const { args: { 0: emittedAssetId } } = await expectEvent.inTransaction( + tx.tx, PAMActor, 'ProgressedAsset' + ); + + const storedNextState = web3ResponseToState(await this.PAMRegistryInstance.getState(web3.utils.toHex(this.assetId))); + const isEventSettled = await this.PAMRegistryInstance.isEventSettled(web3.utils.toHex(this.assetId), _event); + const projectedNextState = web3ResponseToState(await this.PAMEngineInstance.computeStateForEvent( + this.terms, + this.state, + _event, + web3.utils.toHex(0) + )); + const storedNextEvent = await this.PAMRegistryInstance.getNextScheduledEvent(web3.utils.toHex(this.assetId)); + + assert.equal(emittedAssetId, this.assetId); + assert.notEqual(storedNextEvent, _event); + assert.equal(storedNextState.statusDate, eventTime); + assert.equal(isEventSettled[0], true); + assert.equal(isEventSettled[1].toString(), payoff.toFixed()); + assert.deepEqual(storedNextState, projectedNextState); + + await revertToSnapshot(snapshot_asset); + snapshot_asset = await createSnapshot(); + }); +}); diff --git a/packages/ap-contracts/test/helper/setupTestEnvironment.js b/packages/ap-contracts/test/helper/setupTestEnvironment.js index 8b7bda1b..54ab271b 100644 --- a/packages/ap-contracts/test/helper/setupTestEnvironment.js +++ b/packages/ap-contracts/test/helper/setupTestEnvironment.js @@ -10,6 +10,12 @@ const CEGRegistry = artifacts.require('CEGRegistry'); const CERTFRegistry = artifacts.require('CERTFRegistry'); const PAMRegistry = artifacts.require('PAMRegistry'); +const ANNEncoder = artifacts.require('ANNEncoder'); +const CECEncoder = artifacts.require('CECEncoder'); +const CEGEncoder = artifacts.require('CEGEncoder'); +const CERTFEncoder = artifacts.require('CERTFEncoder'); +const PAMEncoder = artifacts.require('PAMEncoder'); + const ANNActor = artifacts.require('ANNActor'); const CECActor = artifacts.require('CECActor'); const CEGActor = artifacts.require('CEGActor'); @@ -27,8 +33,6 @@ async function setupTestEnvironment (accounts) { const admin = accounts[0]; const instances = {}; - // PAMEngine.numberFormat = 'String'; - // ACTUS-Solidity instances.ANNEngineInstance = await ANNEngine.new(); instances.CECEngineInstance = await CECEngine.new(); @@ -37,6 +41,16 @@ async function setupTestEnvironment (accounts) { instances.PAMEngineInstance = await PAMEngine.new(); // Asset Registry + instances.ANNEncoderInstance = await ANNEncoder.new(); + instances.CECEncoderInstance = await CECEncoder.new(); + instances.CEGEncoderInstance = await CEGEncoder.new(); + instances.CERTFEncoderInstance = await CERTFEncoder.new(); + instances.PAMEncoderInstance = await PAMEncoder.new(); + try { await ANNRegistry.link(instances.ANNEncoderInstance); } catch(error) {} + try { await CECRegistry.link(instances.CECEncoderInstance); } catch(error) {} + try { await CEGRegistry.link(instances.CEGEncoderInstance); } catch(error) {} + try { await CERTFRegistry.link(instances.CERTFEncoderInstance); } catch(error) {} + try { await PAMRegistry.link(instances.PAMEncoderInstance); } catch(error) {} instances.ANNRegistryInstance = await ANNRegistry.new(); instances.CECRegistryInstance = await CECRegistry.new(); instances.CEGRegistryInstance = await CEGRegistry.new(); diff --git a/packages/ap-contracts/test/truffle-fixture.js b/packages/ap-contracts/test/truffle-fixture.js index a2bfd162..853480e3 100644 --- a/packages/ap-contracts/test/truffle-fixture.js +++ b/packages/ap-contracts/test/truffle-fixture.js @@ -10,6 +10,12 @@ const CEGRegistry = artifacts.require('CEGRegistry'); const CERTFRegistry = artifacts.require('CERTFRegistry'); const PAMRegistry = artifacts.require('PAMRegistry'); +const ANNEncoder = artifacts.require('ANNEncoder'); +const CECEncoder = artifacts.require('CECEncoder'); +const CEGEncoder = artifacts.require('CEGEncoder'); +const CERTFEncoder = artifacts.require('CERTFEncoder'); +const PAMEncoder = artifacts.require('PAMEncoder'); + const ANNActor = artifacts.require('ANNActor'); const CECActor = artifacts.require('CECActor'); const CEGActor = artifacts.require('CEGActor'); @@ -35,6 +41,21 @@ module.exports = async (accounts) => { PAMEngine.setAsDeployed(PAMEngineInstance); // Asset Registry + const ANNEncoderInstance = await ANNEncoder.new(); + ANNEncoder.setAsDeployed(ANNEncoderInstance); + const CECEncoderInstance = await CECEncoder.new(); + CECEncoder.setAsDeployed(CECEncoderInstance); + const CEGEncoderInstance = await CEGEncoder.new(); + CEGEncoder.setAsDeployed(CEGEncoderInstance); + const CERTFEncoderInstance = await CERTFEncoder.new(); + CERTFEncoder.setAsDeployed(CERTFEncoderInstance); + const PAMEncoderInstance = await PAMEncoder.new(); + PAMEncoder.setAsDeployed(PAMEncoderInstance); + try { await ANNRegistry.link(ANNEncoderInstance); } catch(error) {} + try { await CECRegistry.link(CECEncoderInstance); } catch(error) {} + try { await CEGRegistry.link(CEGEncoderInstance); } catch(error) {} + try { await CERTFRegistry.link(CERTFEncoderInstance); } catch(error) {} + try { await PAMRegistry.link(PAMEncoderInstance); } catch(error) {} const ANNRegistryInstance = await ANNRegistry.new(); ANNRegistry.setAsDeployed(ANNRegistryInstance); const CECRegistryInstance = await CECRegistry.new(); diff --git a/packages/ap-contracts/ts-bindings/ANNEngine.d.ts b/packages/ap-contracts/ts-bindings/ANNEngine.d.ts index 59cd1ae2..2b089506 100644 --- a/packages/ap-contracts/ts-bindings/ANNEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/ANNEngine.d.ts @@ -561,6 +561,89 @@ export class ANNEngine extends Contract { eventType: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + scalingEffect: number | string; + penaltyType: number | string; + feeBasis: number | string; + currency: string; + settlementCurrency: string; + marketObjectCodeRateReset: string | number[]; + contractDealDate: number | string; + statusDate: number | string; + initialExchangeDate: number | string; + maturityDate: number | string; + purchaseDate: number | string; + capitalizationEndDate: number | string; + cycleAnchorDateOfInterestPayment: number | string; + cycleAnchorDateOfRateReset: number | string; + cycleAnchorDateOfScalingIndex: number | string; + cycleAnchorDateOfFee: number | string; + cycleAnchorDateOfPrincipalRedemption: number | string; + notionalPrincipal: number | string; + nominalInterestRate: number | string; + accruedInterest: number | string; + rateMultiplier: number | string; + rateSpread: number | string; + nextResetRate: number | string; + feeRate: number | string; + feeAccrued: number | string; + penaltyRate: number | string; + delinquencyRate: number | string; + premiumDiscountAtIED: number | string; + priceAtPurchaseDate: number | string; + nextPrincipalRedemptionPayment: number | string; + lifeCap: number | string; + lifeFloor: number | string; + periodCap: number | string; + periodFloor: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfInterestPayment: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfRateReset: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfScalingIndex: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfFee: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfPrincipalRedemption: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( arg0: string | number[], arg1: { diff --git a/packages/ap-contracts/ts-bindings/ANNRegistry.d.ts b/packages/ap-contracts/ts-bindings/ANNRegistry.d.ts index 9accd6b1..5ca46c79 100644 --- a/packages/ap-contracts/ts-bindings/ANNRegistry.d.ts +++ b/packages/ap-contracts/ts-bindings/ANNRegistry.d.ts @@ -578,12 +578,6 @@ export class ANNRegistry extends Contract { 1: string; 2: string; }>; - IncrementedScheduleIndex: ContractEvent<{ - assetId: string; - nextScheduleIndex: string; - 0: string; - 1: string; - }>; RegisteredAsset: ContractEvent; RevokedAccess: ContractEvent<{ assetId: string; diff --git a/packages/ap-contracts/ts-bindings/BaseRegistry.d.ts b/packages/ap-contracts/ts-bindings/BaseRegistry.d.ts index 263eca9a..972185ea 100644 --- a/packages/ap-contracts/ts-bindings/BaseRegistry.d.ts +++ b/packages/ap-contracts/ts-bindings/BaseRegistry.d.ts @@ -320,12 +320,6 @@ export class BaseRegistry extends Contract { 1: string; 2: string; }>; - IncrementedScheduleIndex: ContractEvent<{ - assetId: string; - nextScheduleIndex: string; - 0: string; - 1: string; - }>; RegisteredAsset: ContractEvent; RevokedAccess: ContractEvent<{ assetId: string; diff --git a/packages/ap-contracts/ts-bindings/CECEngine.d.ts b/packages/ap-contracts/ts-bindings/CECEngine.d.ts index 04dd79f1..8a8b539a 100644 --- a/packages/ap-contracts/ts-bindings/CECEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/CECEngine.d.ts @@ -306,6 +306,38 @@ export class CECEngine extends Contract { arg3: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + creditEventTypeCovered: number | string; + feeBasis: number | string; + statusDate: number | string; + maturityDate: number | string; + notionalPrincipal: number | string; + feeRate: number | string; + coverageOfCreditEnhancement: number | string; + contractReference_1: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + contractReference_2: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( arg0: string | number[], arg1: { diff --git a/packages/ap-contracts/ts-bindings/CECRegistry.d.ts b/packages/ap-contracts/ts-bindings/CECRegistry.d.ts index 1a542e84..1bf91941 100644 --- a/packages/ap-contracts/ts-bindings/CECRegistry.d.ts +++ b/packages/ap-contracts/ts-bindings/CECRegistry.d.ts @@ -444,12 +444,6 @@ export class CECRegistry extends Contract { 1: string; 2: string; }>; - IncrementedScheduleIndex: ContractEvent<{ - assetId: string; - nextScheduleIndex: string; - 0: string; - 1: string; - }>; RegisteredAsset: ContractEvent; RevokedAccess: ContractEvent<{ assetId: string; diff --git a/packages/ap-contracts/ts-bindings/CEGEngine.d.ts b/packages/ap-contracts/ts-bindings/CEGEngine.d.ts index 1fbfda35..bc0b0578 100644 --- a/packages/ap-contracts/ts-bindings/CEGEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/CEGEngine.d.ts @@ -406,6 +406,58 @@ export class CEGEngine extends Contract { eventType: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + feeBasis: number | string; + creditEventTypeCovered: number | string; + currency: string; + settlementCurrency: string; + contractDealDate: number | string; + statusDate: number | string; + maturityDate: number | string; + purchaseDate: number | string; + cycleAnchorDateOfFee: number | string; + notionalPrincipal: number | string; + delinquencyRate: number | string; + feeAccrued: number | string; + feeRate: number | string; + priceAtPurchaseDate: number | string; + coverageOfCreditEnhancement: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfFee: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + contractReference_1: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + contractReference_2: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( _event: string | number[], arg1: { diff --git a/packages/ap-contracts/ts-bindings/CEGRegistry.d.ts b/packages/ap-contracts/ts-bindings/CEGRegistry.d.ts index 4adfd20f..40c5e226 100644 --- a/packages/ap-contracts/ts-bindings/CEGRegistry.d.ts +++ b/packages/ap-contracts/ts-bindings/CEGRegistry.d.ts @@ -495,12 +495,6 @@ export class CEGRegistry extends Contract { 1: string; 2: string; }>; - IncrementedScheduleIndex: ContractEvent<{ - assetId: string; - nextScheduleIndex: string; - 0: string; - 1: string; - }>; RegisteredAsset: ContractEvent; RevokedAccess: ContractEvent<{ assetId: string; diff --git a/packages/ap-contracts/ts-bindings/CERTFEngine.d.ts b/packages/ap-contracts/ts-bindings/CERTFEngine.d.ts index 30091734..13b2fa0f 100644 --- a/packages/ap-contracts/ts-bindings/CERTFEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/CERTFEngine.d.ts @@ -522,6 +522,82 @@ export class CERTFEngine extends Contract { eventType: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + contractPerformance: number | string; + couponType: number | string; + currency: string; + settlementCurrency: string; + contractDealDate: number | string; + statusDate: number | string; + initialExchangeDate: number | string; + maturityDate: number | string; + nonPerformingDate: number | string; + issueDate: number | string; + cycleAnchorDateOfRedemption: number | string; + cycleAnchorDateOfTermination: number | string; + cycleAnchorDateOfCoupon: number | string; + nominalPrice: number | string; + issuePrice: number | string; + quantity: number | string; + denominationRatio: number | string; + couponRate: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + settlementPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + fixingPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + exercisePeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfRedemption: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfTermination: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfCoupon: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + contractReference_1: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( arg0: string | number[], arg1: { diff --git a/packages/ap-contracts/ts-bindings/CERTFRegistry.d.ts b/packages/ap-contracts/ts-bindings/CERTFRegistry.d.ts index af2618a2..23f0fccd 100644 --- a/packages/ap-contracts/ts-bindings/CERTFRegistry.d.ts +++ b/packages/ap-contracts/ts-bindings/CERTFRegistry.d.ts @@ -545,12 +545,6 @@ export class CERTFRegistry extends Contract { 1: string; 2: string; }>; - IncrementedScheduleIndex: ContractEvent<{ - assetId: string; - nextScheduleIndex: string; - 0: string; - 1: string; - }>; RegisteredAsset: ContractEvent; RevokedAccess: ContractEvent<{ assetId: string; diff --git a/packages/ap-contracts/ts-bindings/IANNEngine.d.ts b/packages/ap-contracts/ts-bindings/IANNEngine.d.ts index 3a192ac0..d287b4bf 100644 --- a/packages/ap-contracts/ts-bindings/IANNEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/IANNEngine.d.ts @@ -437,6 +437,89 @@ export class IANNEngine extends Contract { segmentEnd: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + scalingEffect: number | string; + penaltyType: number | string; + feeBasis: number | string; + currency: string; + settlementCurrency: string; + marketObjectCodeRateReset: string | number[]; + contractDealDate: number | string; + statusDate: number | string; + initialExchangeDate: number | string; + maturityDate: number | string; + purchaseDate: number | string; + capitalizationEndDate: number | string; + cycleAnchorDateOfInterestPayment: number | string; + cycleAnchorDateOfRateReset: number | string; + cycleAnchorDateOfScalingIndex: number | string; + cycleAnchorDateOfFee: number | string; + cycleAnchorDateOfPrincipalRedemption: number | string; + notionalPrincipal: number | string; + nominalInterestRate: number | string; + accruedInterest: number | string; + rateMultiplier: number | string; + rateSpread: number | string; + nextResetRate: number | string; + feeRate: number | string; + feeAccrued: number | string; + penaltyRate: number | string; + delinquencyRate: number | string; + premiumDiscountAtIED: number | string; + priceAtPurchaseDate: number | string; + nextPrincipalRedemptionPayment: number | string; + lifeCap: number | string; + lifeFloor: number | string; + periodCap: number | string; + periodFloor: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfInterestPayment: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfRateReset: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfScalingIndex: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfFee: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfPrincipalRedemption: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + computeCyclicScheduleSegment( terms: { contractType: number | string; diff --git a/packages/ap-contracts/ts-bindings/ICECEngine.d.ts b/packages/ap-contracts/ts-bindings/ICECEngine.d.ts index 22a63e6b..56753721 100644 --- a/packages/ap-contracts/ts-bindings/ICECEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/ICECEngine.d.ts @@ -266,6 +266,38 @@ export class ICECEngine extends Contract { eventType: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + creditEventTypeCovered: number | string; + feeBasis: number | string; + statusDate: number | string; + maturityDate: number | string; + notionalPrincipal: number | string; + feeRate: number | string; + coverageOfCreditEnhancement: number | string; + contractReference_1: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + contractReference_2: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( _event: string | number[], terms: { diff --git a/packages/ap-contracts/ts-bindings/ICEGEngine.d.ts b/packages/ap-contracts/ts-bindings/ICEGEngine.d.ts index 3dcda09d..dffcee24 100644 --- a/packages/ap-contracts/ts-bindings/ICEGEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/ICEGEngine.d.ts @@ -366,6 +366,58 @@ export class ICEGEngine extends Contract { eventType: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + feeBasis: number | string; + creditEventTypeCovered: number | string; + currency: string; + settlementCurrency: string; + contractDealDate: number | string; + statusDate: number | string; + maturityDate: number | string; + purchaseDate: number | string; + cycleAnchorDateOfFee: number | string; + notionalPrincipal: number | string; + delinquencyRate: number | string; + feeAccrued: number | string; + feeRate: number | string; + priceAtPurchaseDate: number | string; + coverageOfCreditEnhancement: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfFee: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + contractReference_1: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + contractReference_2: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( _event: string | number[], terms: { diff --git a/packages/ap-contracts/ts-bindings/ICERTFEngine.d.ts b/packages/ap-contracts/ts-bindings/ICERTFEngine.d.ts index c87bd070..84ff19cd 100644 --- a/packages/ap-contracts/ts-bindings/ICERTFEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/ICERTFEngine.d.ts @@ -482,6 +482,82 @@ export class ICERTFEngine extends Contract { eventType: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + contractPerformance: number | string; + couponType: number | string; + currency: string; + settlementCurrency: string; + contractDealDate: number | string; + statusDate: number | string; + initialExchangeDate: number | string; + maturityDate: number | string; + nonPerformingDate: number | string; + issueDate: number | string; + cycleAnchorDateOfRedemption: number | string; + cycleAnchorDateOfTermination: number | string; + cycleAnchorDateOfCoupon: number | string; + nominalPrice: number | string; + issuePrice: number | string; + quantity: number | string; + denominationRatio: number | string; + couponRate: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + settlementPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + fixingPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + exercisePeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfRedemption: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfTermination: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfCoupon: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + contractReference_1: { + object: string | number[]; + object2: string | number[]; + _type: number | string; + role: number | string; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( _event: string | number[], terms: { diff --git a/packages/ap-contracts/ts-bindings/IPAMEngine.d.ts b/packages/ap-contracts/ts-bindings/IPAMEngine.d.ts index a6c1b51f..3ec489ee 100644 --- a/packages/ap-contracts/ts-bindings/IPAMEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/IPAMEngine.d.ts @@ -405,6 +405,81 @@ export class IPAMEngine extends Contract { segmentEnd: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + scalingEffect: number | string; + penaltyType: number | string; + feeBasis: number | string; + currency: string; + settlementCurrency: string; + marketObjectCodeRateReset: string | number[]; + contractDealDate: number | string; + statusDate: number | string; + initialExchangeDate: number | string; + maturityDate: number | string; + purchaseDate: number | string; + capitalizationEndDate: number | string; + cycleAnchorDateOfInterestPayment: number | string; + cycleAnchorDateOfRateReset: number | string; + cycleAnchorDateOfScalingIndex: number | string; + cycleAnchorDateOfFee: number | string; + notionalPrincipal: number | string; + nominalInterestRate: number | string; + accruedInterest: number | string; + rateMultiplier: number | string; + rateSpread: number | string; + nextResetRate: number | string; + feeRate: number | string; + feeAccrued: number | string; + penaltyRate: number | string; + delinquencyRate: number | string; + premiumDiscountAtIED: number | string; + priceAtPurchaseDate: number | string; + lifeCap: number | string; + lifeFloor: number | string; + periodCap: number | string; + periodFloor: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfInterestPayment: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfRateReset: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfScalingIndex: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfFee: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + computeCyclicScheduleSegment( terms: { contractType: number | string; diff --git a/packages/ap-contracts/ts-bindings/PAMEngine.d.ts b/packages/ap-contracts/ts-bindings/PAMEngine.d.ts index d246e008..244e7952 100644 --- a/packages/ap-contracts/ts-bindings/PAMEngine.d.ts +++ b/packages/ap-contracts/ts-bindings/PAMEngine.d.ts @@ -521,6 +521,81 @@ export class PAMEngine extends Contract { eventType: number | string ): TransactionObject; + computeNextCyclicEvent( + terms: { + contractType: number | string; + calendar: number | string; + contractRole: number | string; + dayCountConvention: number | string; + businessDayConvention: number | string; + endOfMonthConvention: number | string; + scalingEffect: number | string; + penaltyType: number | string; + feeBasis: number | string; + currency: string; + settlementCurrency: string; + marketObjectCodeRateReset: string | number[]; + contractDealDate: number | string; + statusDate: number | string; + initialExchangeDate: number | string; + maturityDate: number | string; + purchaseDate: number | string; + capitalizationEndDate: number | string; + cycleAnchorDateOfInterestPayment: number | string; + cycleAnchorDateOfRateReset: number | string; + cycleAnchorDateOfScalingIndex: number | string; + cycleAnchorDateOfFee: number | string; + notionalPrincipal: number | string; + nominalInterestRate: number | string; + accruedInterest: number | string; + rateMultiplier: number | string; + rateSpread: number | string; + nextResetRate: number | string; + feeRate: number | string; + feeAccrued: number | string; + penaltyRate: number | string; + delinquencyRate: number | string; + premiumDiscountAtIED: number | string; + priceAtPurchaseDate: number | string; + lifeCap: number | string; + lifeFloor: number | string; + periodCap: number | string; + periodFloor: number | string; + gracePeriod: { i: number | string; p: number | string; isSet: boolean }; + delinquencyPeriod: { + i: number | string; + p: number | string; + isSet: boolean; + }; + cycleOfInterestPayment: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfRateReset: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfScalingIndex: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + cycleOfFee: { + i: number | string; + p: number | string; + s: number | string; + isSet: boolean; + }; + }, + lastScheduleTime: number | string, + eventType: number | string + ): TransactionObject; + isEventScheduled( arg0: string | number[], arg1: { diff --git a/packages/ap-contracts/ts-bindings/PAMRegistry.d.ts b/packages/ap-contracts/ts-bindings/PAMRegistry.d.ts index e5d9f894..80ce1c27 100644 --- a/packages/ap-contracts/ts-bindings/PAMRegistry.d.ts +++ b/packages/ap-contracts/ts-bindings/PAMRegistry.d.ts @@ -554,12 +554,6 @@ export class PAMRegistry extends Contract { 1: string; 2: string; }>; - IncrementedScheduleIndex: ContractEvent<{ - assetId: string; - nextScheduleIndex: string; - 0: string; - 1: string; - }>; RegisteredAsset: ContractEvent; RevokedAccess: ContractEvent<{ assetId: string; diff --git a/packages/ap-contracts/ts-bindings/ScheduleRegistry.d.ts b/packages/ap-contracts/ts-bindings/ScheduleRegistry.d.ts index 775c75dc..878bb813 100644 --- a/packages/ap-contracts/ts-bindings/ScheduleRegistry.d.ts +++ b/packages/ap-contracts/ts-bindings/ScheduleRegistry.d.ts @@ -275,12 +275,6 @@ export class ScheduleRegistry extends Contract { 1: string; 2: string; }>; - IncrementedScheduleIndex: ContractEvent<{ - assetId: string; - nextScheduleIndex: string; - 0: string; - 1: string; - }>; RevokedAccess: ContractEvent<{ assetId: string; account: string;