diff --git a/src/hub/Hub.sol b/src/hub/Hub.sol index 7fd45dd..ca3ee3c 100644 --- a/src/hub/Hub.sol +++ b/src/hub/Hub.sol @@ -163,7 +163,7 @@ contract Hub is Circles, IHubV2 { /** * @notice Constructor for the Hub contract. * @param _hubV1 address of the Hub v1 contract - * @param _inflation_day_zero timestamp of the start of the global inflation curve. + * @param _inflationDayZero timestamp of the start of the global inflation curve. * For deployment on Gnosis Chain this parameter should be set to midnight 15 October 2020, * or in unix time 1602786330 (deployment at 6:25:30 pm UTC) - 66330 (offset to midnight) = 1602720000. * @param _standardTreasury address of the standard treasury contract @@ -174,11 +174,11 @@ contract Hub is Circles, IHubV2 { constructor( IHubV1 _hubV1, address _migration, - uint256 _inflation_day_zero, + uint256 _inflationDayZero, address _standardTreasury, uint256 _bootstrapTime, string memory _fallbackUri - ) Circles(_inflation_day_zero, _fallbackUri) { + ) Circles(_inflationDayZero, _fallbackUri) { require(address(_hubV1) != address(0), "Hub v1 address can not be zero."); require(_standardTreasury != address(0), "Standard treasury address can not be zero."); @@ -854,7 +854,7 @@ contract Hub is Circles, IHubV2 { Stream[] calldata _streams, uint16[] memory _coordinates ) internal returns (int256[] memory) { - // intialiaze netted flow + // initialize netted flow int256[] memory nettedFlow = new int256[](_flowVertices.length); // effect the stream transfers with acceptance calls @@ -1025,8 +1025,6 @@ contract Hub is Circles, IHubV2 { avatars[SENTINEL] = _avatar; } - // Private functions - /** * @dev abi.encodePacked of an array uint16[] would still pad each uint16 - I think; * if abi packing does not add padding this function is redundant and should be thrown out @@ -1037,7 +1035,7 @@ contract Hub is Circles, IHubV2 { * @return unpackedCoordinates_ An array of unpacked coordinates (of length 3* numberOfTriplets) */ function _unpackCoordinates(bytes calldata _packedData, uint256 _numberOfTriplets) - private + internal pure returns (uint16[] memory unpackedCoordinates_) { @@ -1054,6 +1052,8 @@ contract Hub is Circles, IHubV2 { } } + // Private functions + /** * @dev Internal function to upsert a trust marker for a truster and a trusted address. * It will initialize the linked list for the truster if it does not exist yet. diff --git a/test/circles/Circles.t.sol b/test/circles/Circles.t.sol index 070c2d3..c7b5373 100644 --- a/test/circles/Circles.t.sol +++ b/test/circles/Circles.t.sol @@ -31,12 +31,12 @@ contract CirclesTest is Test, TimeSetup, Approximation { function setUp() public { // set time to 15th October 2020 - _setUpTime(DEMURRAGE_DAY_ZERO + 1); + _setUpTime(INFLATION_DAY_ZERO + 1); // 23 january 2024 12:01 am UTC _forwardTime(DAY0 * 1 days); - circles = new MockCircles(DEMURRAGE_DAY_ZERO); + circles = new MockCircles(INFLATION_DAY_ZERO); for (uint256 i = 0; i < N; i++) { addresses[i] = makeAddr(avatars[i]); diff --git a/test/hub/Hub.t.sol b/test/hub/Hub.t.sol new file mode 100644 index 0000000..55b4c42 --- /dev/null +++ b/test/hub/Hub.t.sol @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.13; + +import {Test} from "forge-std/Test.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; + +import "../setup/TimeSetup.sol"; +import "../setup/HumanRegistration.sol"; +import "./MockPathTransferHub.sol"; + +contract HubPathTransferTest is Test, TimeSetup, HumanRegistration { + // Constants + + uint256 public constant CRC = uint256(10 ** 18); + + // State variables + + MockPathTransferHub public mockHub; + + constructor() HumanRegistration(4) {} + + // Setup + + function setUp() public { + startTime(); + mockHub = new MockPathTransferHub(INFLATION_DAY_ZERO, 365 days); + } + + // Tests + + function testOperateFlowMatrix() public {} +} diff --git a/test/hub/MockPathTransferHub.sol b/test/hub/MockPathTransferHub.sol new file mode 100644 index 0000000..1cd89d8 --- /dev/null +++ b/test/hub/MockPathTransferHub.sol @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.13; + +import "../../src/migration/IHub.sol"; +import "../../src/hub/Hub.sol"; +import "../../src/migration/IHub.sol"; + +contract MockPathTransferHub is Hub { + // Constructor + + constructor(uint256 _inflationDayZero, uint256 _bootstrapTime) + Hub(IHubV1(address(1)), address(0), _inflationDayZero, address(1), _bootstrapTime, "") + {} + + // External functions + + function registerHumanUnrestricted() external { + address human = msg.sender; + + // insert avatar into linked list; reverts if it already exists + _insertAvatar(human); + + // set the last mint time to the current timestamp for invited human + // and register the v1 Circles contract status as unregistered + address v1CirclesStatus = address(0); + MintTime storage mintTime = mintTimes[human]; + mintTime.mintV1Status = v1CirclesStatus; + mintTime.lastMintTime = uint96(block.timestamp); + + // trust self indefinitely, cannot be altered later + _trust(human, human, INDEFINITE_FUTURE); + } + + // Public functions + + function accessUnpackCoordinates(bytes calldata _packedData, uint256 _numberOfTriplets) + public + pure + returns (uint16[] memory unpackedCoordinates_) + { + return super._unpackCoordinates(_packedData, _numberOfTriplets); + } + + // Private functions + + function notMocked() private pure { + assert(false); + } +} diff --git a/test/migration/Migration.t.sol b/test/migration/Migration.t.sol index d584b49..18e6de0 100644 --- a/test/migration/Migration.t.sol +++ b/test/migration/Migration.t.sol @@ -12,6 +12,7 @@ contract GraphTest is Test { uint256 private ACCURACY_ONE = uint256(10 ** 8); uint256 private ACCURACY_ONE_HUNDREDTH = uint256(10 ** 6); + // 6:00:18 pm UTC | Monday, December 11, 2023 uint256 private MOMENT_IN_TIME = uint256(1702317618); // State variables @@ -20,6 +21,8 @@ contract GraphTest is Test { Migration public migration; + // Setup + function setUp() public { mockHubV1 = new MockHubV1(); @@ -28,6 +31,8 @@ contract GraphTest is Test { vm.warp(MOMENT_IN_TIME); } + // Tests + function testConversionMigrationV1ToTimeCircles() public { // `MOMENT_IN_TIME` is in the third period assertEq(uint256(3), mockHubV1.periods()); diff --git a/test/setup/HumanRegistration.sol b/test/setup/HumanRegistration.sol new file mode 100644 index 0000000..28f4869 --- /dev/null +++ b/test/setup/HumanRegistration.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: AGPL-3.0-only +pragma solidity >=0.8.13; + +import {Test} from "forge-std/Test.sol"; +import {StdCheats} from "forge-std/StdCheats.sol"; + +contract HumanRegistration is Test { + // Constants + uint256 public immutable N; + + // State variables + + // forgefmt: disable-next-line + string[50] public avatars = ["Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace", "Hank", "Ivy", "Jack", "Kathy", "Liam", "Mia", "Noah", "Olivia", "Parker", "Quinn", "Ruby", "Steve", "Tina", "Umar", "Violet", "Wes", "Xena", "Yale", "Zara", "Asher", "Bella", "Cody", "Daisy", "Edward", "Fiona", "George", "Holly", "Ian", "Jenna", "Kevin", "Luna", "Mason", "Nina", "Oscar", "Piper", "Quincy", "Rosa", "Sam", "Troy", "Una", "Victor", "Wendy", "Xander"]; + + address[] public addresses; + address[] public sortedAddresses; + uint256[] public permutationMap; + + // Public functions + + constructor(uint16 _n) { + require(_n <= 50, "N must be less than or equal to 50"); + N = _n; + addresses = new address[](N); + sortedAddresses = new address[](N); + permutationMap = new uint256[](N); + for (uint256 i = 0; i < N; i++) { + addresses[i] = makeAddr(avatars[i]); + } + sortAddressesWithPermutationMap(); + } + + // Private functions + + /** + * @dev Sorts an array of addresses in ascending order using Bubble Sort + * and returns the permutation map. This is not meant to be an efficient sort, + * rather the simplest implementation for transparancy of the test. + */ + function sortAddressesWithPermutationMap() private { + uint256 length = addresses.length; + sortedAddresses = addresses; + + // Initialize the permutation map with original indices + for (uint256 i = 0; i < length; i++) { + permutationMap[i] = i; + } + + // Bubble sort the array and the permutation map + for (uint256 i = 0; i < length; i++) { + for (uint256 j = 0; j < length - i - 1; j++) { + if (sortedAddresses[j] > sortedAddresses[j + 1]) { + // Swap elements in the address array + (sortedAddresses[j], sortedAddresses[j + 1]) = (sortedAddresses[j + 1], sortedAddresses[j]); + // Swap corresponding elements in the permutation map + (permutationMap[j], permutationMap[j + 1]) = (permutationMap[j + 1], permutationMap[j]); + } + } + } + } +} diff --git a/test/setup/TimeSetup.sol b/test/setup/TimeSetup.sol index 2d3a0e0..b603e40 100644 --- a/test/setup/TimeSetup.sol +++ b/test/setup/TimeSetup.sol @@ -5,22 +5,22 @@ import {Test} from "forge-std/Test.sol"; import {StdCheats} from "forge-std/StdCheats.sol"; contract TimeSetup is Test { - // must match circles/TemporalDiscount.sol/ZERO_TIME + /** + * Arbitrary origin for counting time since 10 December 2021 + * "Hope" is the thing with feathers - + */ uint256 internal constant ZERO_TIME = uint256(1639094400); // Start of day zero on Gnosis Chain is midgnight 15th Octorer 2020 - uint256 internal constant DEMURRAGE_DAY_ZERO = uint256(1602720000); + uint256 internal constant INFLATION_DAY_ZERO = uint256(1602720000); + + uint256 internal constant ONE_YEAR_BOOTSTRAP = uint256(31536000); function startTime() public { // Earliest sensible start time is ZERO_TIME plus one second vm.warp(ZERO_TIME + 1); } - // function startDemurrageTime() public { - // // Earliest sensible start time is DEMURRAGE_DAY_ZERO plus one second - // vm.warp(DEMURRAGE_DAY_ZERO + 1); - // } - // vm.skip was not working, so just do it manually // todo: figure foundry test issues out with vm.skip function skipTime(uint256 _duration) public {