Skip to content

Commit

Permalink
(test/Circles): test issuance, consecutive periods
Browse files Browse the repository at this point in the history
benjaminbollen committed Mar 28, 2024
1 parent 23ecf4d commit 53b2741
Showing 2 changed files with 61 additions and 29 deletions.
55 changes: 28 additions & 27 deletions test/circles/Circles.t.sol
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ contract CirclesTest is Test, TimeCirclesSetup, Approximation {

uint256 public constant N = 4;

uint256 public constant EPS = 10 ** (18 - 1);
uint256 public constant EPS = 10 ** (18 - 2);
uint256 public constant FEMTO_EPS = 10 ** (18 - 15);

// State variables
@@ -40,33 +40,12 @@ contract CirclesTest is Test, TimeCirclesSetup, Approximation {
}

function testCalculateIssuance() public {
uint256 day = circles.day(block.timestamp);
(uint256 issuance,,) = circles.calculateIssuance(addresses[0]);
assertEq(issuance, 0);
for (uint256 i = 0; i < 100; i++) {
// Generate a pseudo-random number of seconds between 0 and 12 days (avoid edge cases in this test)
uint256 secondsSkip = uint256(keccak256(abi.encodePacked(block.timestamp, i, uint256(2)))) % 16 days;

skipTime(30 minutes);
// still the same day
(issuance,,) = circles.calculateIssuance(addresses[0]);
assertEq(issuance, 0);

skipTime(31 minutes);
(issuance,,) = circles.calculateIssuance(addresses[0]);
assertEq(issuance, 1 * CRC);

skipTime(1 days + 2 hours + 15 minutes);
(issuance,,) = circles.calculateIssuance(addresses[0]);
assertTrue(approximatelyEqual(issuance, 27 * CRC, EPS));

skipTime(1 hours + 40 minutes);
(issuance,,) = circles.calculateIssuance(addresses[0]);
console.log("issuance", issuance);

assertTrue(approximatelyEqual(issuance, 28 * CRC, EPS));

vm.prank(addresses[0]);
circles.claimIssuance();
uint256 balance = circles.balanceOf(addresses[0], circlesIdentifiers[0]);
assertTrue(approximatelyEqual(balance, 28 * CRC, EPS));
_skipAndMint(secondsSkip, addresses[0]);
}
}

function testConsecutiveClaimablePeriods() public {
@@ -137,4 +116,26 @@ contract CirclesTest is Test, TimeCirclesSetup, Approximation {
// bobInflationaryBalanceAfter - bobInflationaryBalance
// );
}

// Private functions

function _skipAndMint(uint256 _seconds, address _avatar) private {
// ensure the avatar has no issuance already to start with
(uint256 issuance, uint256 startPeriod, uint256 endPeriod) = circles.calculateIssuance(_avatar);
assertEq(issuance, 0, "Ensure avatar has no issuance");

// skip time
skipTime(_seconds);

uint256 balanceBefore = circles.balanceOf(_avatar, uint256(uint160(_avatar)));
(issuance, startPeriod, endPeriod) = circles.calculateIssuance(_avatar);
uint256 hoursCount = (endPeriod - startPeriod) / 1 hours;
// console.log("hoursCount", hoursCount, "days:", hoursCount / 24);
vm.prank(_avatar);
circles.claimIssuance();
uint256 balanceAfter = circles.balanceOf(_avatar, uint256(uint160(_avatar)));
assertEq(balanceAfter - balanceBefore, issuance, "Ensure issuance is minted");
assertTrue(issuance <= hoursCount * CRC, "Ensure issuance is not more than expected");
assertTrue(relativeApproximatelyEqual(issuance, hoursCount * CRC, ONE_PERCENT), "Ensure issuance is correct");
}
}
35 changes: 33 additions & 2 deletions test/utils/Approximation.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,39 @@
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.13;

import "../../src/lib/Math64x64.sol";

contract Approximation {
function approximatelyEqual(uint256 a, uint256 b, uint256 epsilon) public pure returns (bool) {
return a > b ? a - b <= epsilon : b - a <= epsilon;
// Constants

int128 private constant ONE = int128(2 ** 64);

// 1% in 64x64 fixed point: integer approximation of 2**64 / 100
int128 internal constant ONE_PERCENT = int128(184467440737095516);

function approximatelyEqual(uint256 _a, uint256 _b, uint256 _epsilon) public pure returns (bool) {
return _a > _b ? _a - _b <= _epsilon : _b - _a <= _epsilon;
}

function relativeApproximatelyEqual(uint256 _a, uint256 _b, int128 _epsilon) public pure returns (bool) {
require(_epsilon >= 0, "Approximation: negative epsilon");
require(_epsilon <= ONE, "Approximation: epsilon too large");
if (_a == _b) {
return true;
}
if (_a == 0 || _b == 0) {
return _epsilon == ONE;
}

// calculate the absolute difference
uint256 diff = _a > _b ? _a - _b : _b - _a;

// use the larger of the two values as denominator
uint256 max = _a > _b ? _a : _b;

// calculate the relative difference
int128 relDiff = Math64x64.divu(diff, max);

return relDiff <= _epsilon;
}
}

0 comments on commit 53b2741

Please sign in to comment.