Skip to content
This repository has been archived by the owner on Aug 6, 2021. It is now read-only.

Commit

Permalink
Merge pull request #87 from atpar/dev
Browse files Browse the repository at this point in the history
Merge dev into master
  • Loading branch information
jo-es authored Dec 31, 2020
2 parents b8dc112 + a473a88 commit 3dd87cd
Show file tree
Hide file tree
Showing 36 changed files with 537 additions and 507 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ This is a monorepo containing all packages related to the ACTUS Protocol.

| Package | Description |
|----------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
| [`protocol`](https://github.com/atpar/ap-monorepo/tree/master/packages/protocol) | Contains the Solidity implementation the ACTUS Protocol and the typescript sdk |
| [`protocol`](packages/protocol/README.md) | Contains the Solidity implementation the ACTUS Protocol and the typescript sdk |

## Development
### Requirements
Expand Down
2 changes: 1 addition & 1 deletion packages/protocol/.solcover.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ module.exports = {
'ACTUS/test/STK/TestSTKPOF.sol',
'ACTUS/test/STK/TestSTKSTF.sol',
'ACTUS/test/TestCore.sol',
'ACTUS/test/TestSignedMath.sol',
'ACTUS/test/TestFixedPointMath.sol',
'SettlementToken.sol',
'NoSettlementToken.sol',
'ERC20Token.sol',
Expand Down
22 changes: 11 additions & 11 deletions packages/protocol/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const ap = await AP.init(web3, ADDRESS_BOOK);
## Development

### Requirements and Setup
See [README](https://github.com/atpar/ap-monorepo) in root directory.
See [README](../../README.md) in root directory.

### Testing
```sh
Expand Down Expand Up @@ -127,13 +127,13 @@ With the exception of Array types, ACTUS types are one to one mapped in Solidity

### Updating ACTUS types througout the project
If the underlying ACTUS types change in [atpar/actus-dictionary](https://github.com/atpar/actus-dictionary)
the following files and directories may be affected and have to be updated manually:
- [ACTUSTypes.sol](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/contracts/ACTUS/Core/ACTUSTypes.sol)
- [Encoder libaries e.g. ANNEncoder](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/contracts/Core/ANN/ANNEncoder.sol)
- [ACTUS.ts](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/src/types/ACTUS.ts)
- [AP.ts](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/src/types/AP.ts)
- [Dictionary.ts](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/src/types/dictionary/dictionary.json)
- [Constants.ts](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/src/utils/Constants.ts)
- [Conversions.ts](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/src/utils/Conversion.ts)
- [Schedule.ts](https://github.com/atpar/ap-monorepo/blob/dev/packages/protocol/src/utils/Schedule.ts)
- [Test helpers](https://github.com/atpar/ap-monorepo/tree/dev/packages/protocol/test/helper)
, the following files and directories may be affected and have to be updated manually:
- [ACTUSTypes.sol](contracts/ACTUS/Core/ACTUSTypes.sol)
| [Encoder libaries e.g. ANNEncoder](contracts/Core/ANN/ANNEncoder.sol)
| [ACTUS.ts](src/types/ACTUS.ts)
| [AP.ts](src/types/AP.ts)
| [Dictionary.ts](src/types/dictionary/dictionary.json)
| [Constants.ts](src/utils/Constants.ts)
| [Conversions.ts](src/utils/Conversion.ts)
| [Schedule.ts](src/utils/Schedule.ts)
| [Test helpers](test/helper)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import "../../../external/BokkyPooBah/BokkyPooBahsDateTimeLibrary.sol";
import "../ACTUSTypes.sol";
import "../ACTUSConstants.sol";

import "../SignedMath.sol";
import "../FixedPointMath.sol";


/**
Expand All @@ -19,10 +19,10 @@ contract DayCountConventions is ACTUSConstants {

using SafeMath for uint;
using SignedSafeMath for int;
using SignedMath for int;
using FixedPointMath for int;

/**
* Returns the fraction of the year between two timestamps.
* Returns the fraction of the year between two timestamps (as a fixed point number multiplied by 10 ** 18).
*/
function yearFraction(
uint256 startTimestamp,
Expand Down Expand Up @@ -76,19 +76,21 @@ contract DayCountConventions is ACTUSConstants {
int256 firstBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(startTime)) ? 366 : 365;

if (d1Year == d2Year) {
return int256(BokkyPooBahsDateTimeLibrary.diffDays(startTime, endTime)).floatDiv(firstBasis);
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return int256(BokkyPooBahsDateTimeLibrary.diffDays(startTime, endTime)).fixedDiv(firstBasis);
}

int256 secondBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(endTime)) ? 366 : 365;

// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
int256 firstFraction = int256(BokkyPooBahsDateTimeLibrary.diffDays(
startTime,
BokkyPooBahsDateTimeLibrary.timestampFromDate(d1Year.add(1), 1, 1)
)).floatDiv(firstBasis);
)).fixedDiv(firstBasis);
int256 secondFraction = int256(BokkyPooBahsDateTimeLibrary.diffDays(
BokkyPooBahsDateTimeLibrary.timestampFromDate(d2Year, 1, 1),
endTime
)).floatDiv(secondBasis);
)).fixedDiv(secondBasis);

return firstFraction.add(secondFraction).add(int256(d2Year.sub(d1Year).sub(1)));
}
Expand All @@ -101,7 +103,8 @@ contract DayCountConventions is ACTUSConstants {
pure
returns (int256)
{
return (int256((endTime.sub(startTime)).div(86400)).floatDiv(360));
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return (int256((endTime.sub(startTime)).div(86400)).fixedDiv(360));
}

/**
Expand All @@ -112,7 +115,8 @@ contract DayCountConventions is ACTUSConstants {
pure
returns (int256)
{
return (int256((endTime.sub(startTime)).div(86400)).floatDiv(365));
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return (int256((endTime.sub(startTime)).div(86400)).fixedDiv(365));
}

/**
Expand Down Expand Up @@ -146,7 +150,8 @@ contract DayCountConventions is ACTUSConstants {
int256 delM = int256(d2Month).sub(int256(d1Month));
int256 delY = int256(d2Year).sub(int256(d1Year));

return ((delY.mul(360).add(delM.mul(30)).add(delD)).floatDiv(360));
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return ((delY.mul(360).add(delM.mul(30)).add(delD)).fixedDiv(360));
}

/**
Expand Down Expand Up @@ -180,7 +185,8 @@ contract DayCountConventions is ACTUSConstants {
int256 delM = int256(d2Month).sub(int256(d1Month));
int256 delY = int256(d2Year).sub(int256(d1Year));

return ((delY.mul(360).add(delM.mul(30)).add(delD)).floatDiv(360));
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return ((delY.mul(360).add(delM.mul(30)).add(delD)).fixedDiv(360));
}

/**
Expand All @@ -207,7 +213,8 @@ contract DayCountConventions is ACTUSConstants {
int256 delM = int256(d2Month).sub(int256(d1Month));
int256 delY = int256(d2Year).sub(int256(d1Year));

return ((delY.mul(336).add(delM.mul(28)).add(delD)).floatDiv(336));
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return ((delY.mul(336).add(delM.mul(28)).add(delD)).fixedDiv(336));
}

/**
Expand All @@ -218,6 +225,7 @@ contract DayCountConventions is ACTUSConstants {
pure
returns (int256)
{
// as fixed point number (10 ** 18)
return ONE_POINT_ZERO;
}

Expand All @@ -229,7 +237,8 @@ contract DayCountConventions is ACTUSConstants {
pure
returns (int256)
{
return int256(ONE_POINT_ZERO).floatDiv(12 * ONE_POINT_ZERO);
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return int256(ONE_POINT_ZERO).fixedDiv(12 * ONE_POINT_ZERO);
}

/**
Expand All @@ -248,21 +257,23 @@ contract DayCountConventions is ACTUSConstants {
int256 firstBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(startTime)) ? 8784 : 8760;

if (d1Year == d2Year) {
return int256(BokkyPooBahsDateTimeLibrary.diffHours(startTime, endTime)).floatDiv(firstBasis);
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return int256(BokkyPooBahsDateTimeLibrary.diffHours(startTime, endTime)).fixedDiv(firstBasis);
}

// no risk of overflow
// 366 * 24, 365 * 24
int256 secondBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(endTime)) ? 8784 : 8760;

// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
int256 firstFraction = int256(BokkyPooBahsDateTimeLibrary.diffHours(
startTime,
BokkyPooBahsDateTimeLibrary.timestampFromDate(d1Year.add(1), 1, 1)
)).floatDiv(firstBasis);
)).fixedDiv(firstBasis);
int256 secondFraction = int256(BokkyPooBahsDateTimeLibrary.diffHours(
BokkyPooBahsDateTimeLibrary.timestampFromDate(d2Year, 1, 1),
endTime
)).floatDiv(secondBasis);
)).fixedDiv(secondBasis);

return firstFraction.add(secondFraction).add(int256(d2Year.sub(d1Year).sub(1)));
}
Expand All @@ -283,21 +294,23 @@ contract DayCountConventions is ACTUSConstants {
int256 firstBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(startTime)) ? 527040 : 525600;

if (d1Year == d2Year) {
return int256(BokkyPooBahsDateTimeLibrary.diffMinutes(startTime, endTime)).floatDiv(firstBasis);
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return int256(BokkyPooBahsDateTimeLibrary.diffMinutes(startTime, endTime)).fixedDiv(firstBasis);
}

// no risk of overflow
// 366 * 1440, 365 * 1440
int256 secondBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(endTime)) ? 527040 : 525600;

// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
int256 firstFraction = int256(BokkyPooBahsDateTimeLibrary.diffMinutes(
startTime,
BokkyPooBahsDateTimeLibrary.timestampFromDate(d1Year.add(1), 1, 1)
)).floatDiv(firstBasis);
)).fixedDiv(firstBasis);
int256 secondFraction = int256(BokkyPooBahsDateTimeLibrary.diffMinutes(
BokkyPooBahsDateTimeLibrary.timestampFromDate(d2Year, 1, 1),
endTime
)).floatDiv(secondBasis);
)).fixedDiv(secondBasis);

return firstFraction.add(secondFraction).add(int256(d2Year.sub(d1Year).sub(1)));
}
Expand All @@ -318,21 +331,23 @@ contract DayCountConventions is ACTUSConstants {
int256 firstBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(startTime)) ? 31622400 : 31536000;

if (d1Year == d2Year) {
return int256(BokkyPooBahsDateTimeLibrary.diffSeconds(startTime, endTime)).floatDiv(firstBasis);
// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
return int256(BokkyPooBahsDateTimeLibrary.diffSeconds(startTime, endTime)).fixedDiv(firstBasis);
}

// no risk of overflow
// 366 * 86400, 365 * 86400
int256 secondBasis = (BokkyPooBahsDateTimeLibrary.isLeapYear(endTime)) ? 31622400 : 31536000;

// fixedDiv on two non fixed point integers returns the quotient in fixed point representation (10 ** 18)
int256 firstFraction = int256(BokkyPooBahsDateTimeLibrary.diffSeconds(
startTime,
BokkyPooBahsDateTimeLibrary.timestampFromDate(d1Year.add(1), 1, 1)
)).floatDiv(firstBasis);
)).fixedDiv(firstBasis);
int256 secondFraction = int256(BokkyPooBahsDateTimeLibrary.diffSeconds(
BokkyPooBahsDateTimeLibrary.timestampFromDate(d2Year, 1, 1),
endTime
)).floatDiv(secondBasis);
)).fixedDiv(secondBasis);

return firstFraction.add(secondFraction).add(int256(d2Year.sub(d1Year).sub(1)));
}
Expand Down
87 changes: 87 additions & 0 deletions packages/protocol/contracts/ACTUS/Core/FixedPointMath.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// "SPDX-License-Identifier: Apache-2.0"
pragma solidity ^0.7.0;


/**
* Fixed point math library for signed integers
*/
library FixedPointMath {

int256 constant private INT256_MIN = -2 ** 255;

uint256 constant public PRECISION = 18;
uint256 constant public MULTIPLICATOR = 10 ** PRECISION;


/**
* @dev The product of a and b has to be less than INT256_MAX (~10 ** 76),
* as devision (normalization) is performed after multiplication
* Upper boundary would be (10 ** 58) * (MULTIPLICATOR) == ~10 ** 76
*/
function fixedMul(int256 a, int256 b) internal pure returns (int256) {
if (a == 0 || b == 0) return 0;

require(
!(a == -1 && b == INT256_MIN),
"FixedPointMath.fixedMul: OVERFLOW_DETECTED"
);

int256 c = a * b;
require(
c / a == b,
"FixedPointMath.fixedMul: OVERFLOW_DETECTED"
);

// normalize (divide by MULTIPLICATOR)
int256 d = c / int256(MULTIPLICATOR);
require(
d != 0,
"FixedPointMath.fixedMul: CANNOT_REPRESENT_GRANULARITY"
);

return d;
}

function fixedDiv(int256 a, int256 b) internal pure returns (int256) {
require(
b != 0,
"FixedPointMath.fixedDiv: DIVIDED_BY_ZERO"
);

if (a == 0) return 0;

// normalize (multiply by MULTIPLICATOR)
int256 c = a * int256(MULTIPLICATOR);
require(
c / a == int256(MULTIPLICATOR),
"FixedPointMath.fixedDiv: OVERFLOW_DETECTED"
);

require(
!(b == -1 && a == INT256_MIN),
"FixedPointMath.fixedDiv: OVERFLOW_DETECTED"
);

int256 d = c / b;
require(
d != 0,
"FixedPointMath.fixedDiv: CANNOT_REPRESENT_GRANULARITY"
);

return d;
}

/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a <= b ? a : b;
}

/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a >= b ? a : b;
}
}
Loading

0 comments on commit 3dd87cd

Please sign in to comment.