/ test / HatsIdUtils.t.sol
HatsIdUtils.t.sol
  1  // SPDX-License-Identifier: UNLICENSED
  2  pragma solidity ^0.8.13;
  3  
  4  import "forge-std/Test.sol";
  5  import "../src/HatsIdUtilities.sol";
  6  import "./LinkableHatsIdUtilities.sol";
  7  
  8  contract LinkedTreeHatIdUtilTests is Test {
  9      LinkableHatsIdUtilities utils;
 10  
 11      error InvalidChildHat();
 12  
 13      function setUp() public {
 14          utils = new LinkableHatsIdUtilities();
 15      }
 16  
 17      function testLinkedHats() public {
 18          uint256 admin = 1 << 224;
 19          uint32 oldTopHat = 2;
 20          uint256 oldTopHatId = uint256(oldTopHat) << 224;
 21          uint256 id1 = utils.buildHatId(admin, 1);
 22          utils.linkTree(oldTopHat, id1);
 23          assertFalse(utils.isTopHat(oldTopHatId));
 24          assertEq(utils.getHatLevel(oldTopHatId), utils.getHatLevel(id1) + 1);
 25          assertEq(utils.getAdminAtLevel(oldTopHatId, 0), admin);
 26  
 27          uint32 admin3 = 3;
 28          uint256 admin3Id = uint256(admin3) << 224;
 29          uint256 id3 = utils.buildHatId(admin3Id, 3);
 30          utils.linkTree(1, id3);
 31          assertEq(utils.getHatLevel(id1), 3);
 32          assertEq(utils.getHatLevel(oldTopHatId), utils.getHatLevel(id1) + 1);
 33          assertEq(utils.getHatLevel(admin), utils.getHatLevel(id3) + 1);
 34          assertEq(utils.getHatLevel(admin3Id), 0);
 35          assertFalse(utils.isTopHat(admin));
 36  
 37          assertEq(utils.getAdminAtLevel(id1, 2), admin);
 38          assertEq(utils.getAdminAtLevel(oldTopHatId, 0), admin3Id);
 39      }
 40  }
 41  
 42  contract HatIdUtilTests is Test {
 43      HatsIdUtilities utils;
 44      uint256 tophatBits = 32;
 45      uint256 levelBits = 16;
 46      uint256 levels = 14;
 47  
 48      function setUp() public {
 49          utils = new HatsIdUtilities();
 50      }
 51  
 52      function testgetHatLevel() public {
 53          for (uint256 i = 1; 2 ** i < type(uint224).max; i += levelBits) {
 54              // each `levelBits` bits corresponds with a level
 55              assertEq(utils.getHatLevel(2 ** i), levels - (i / levelBits));
 56              if (i > 1) {
 57                  assertEq(utils.getHatLevel(2 ** i + (2 ** levelBits)), levels - 1);
 58              }
 59          }
 60      }
 61  
 62      function testBuildHatId() public {
 63          // start with a top hat
 64          uint256 admin = 1 << 224;
 65          uint256 next;
 66          for (uint8 i = 1; i < (levels - 1); i++) {
 67              next = utils.buildHatId(admin, 1);
 68              assertEq(utils.getHatLevel(next), i);
 69              assertEq(utils.getAdminAtLevel(next, i - 1), admin);
 70              admin = next;
 71          }
 72      }
 73  
 74      function testBuildHatIdRevertsAfterMaxLevel() public {
 75          uint256 admin = 0x0000000100010001000100010001000100010001000100010001000100010001;
 76          vm.expectRevert(MaxLevelsReached.selector);
 77          uint256 invalidChild = utils.buildHatId(admin, 1);
 78          console2.log(invalidChild);
 79      }
 80  
 81      function testTopHatDomain() public {
 82          uint256 admin = 1 << 224;
 83          assertEq(utils.isTopHat(admin), true);
 84          assertEq(utils.isTopHat((admin + 1) << 216), false);
 85          assertEq(utils.isTopHat(admin + 1), false);
 86          assertEq(utils.isTopHat(admin - 1), false);
 87  
 88          assertEq(utils.getTopHatDomain(admin + 1), admin >> 224);
 89          assertEq(utils.getTopHatDomain(1), 0);
 90          assertEq(utils.getTopHatDomain(admin - 1), 0);
 91      }
 92  
 93      function testGetAdminAtLocalHatLevel() public {
 94          uint256 hat = 0x000000FF000100020003000400050006000700080009000a000b000c000d000e;
 95          assertEq(utils.getLocalHatLevel(hat), 14);
 96          assertEq(
 97              utils.getAdminAtLocalLevel(hat, 13), 0x000000FF000100020003000400050006000700080009000a000b000c000d0000
 98          );
 99          assertEq(
100              utils.getAdminAtLocalLevel(hat, 12), 0x000000FF000100020003000400050006000700080009000a000b000c00000000
101          );
102      }
103  
104      function testIsValidHatId_Valid() public {
105          uint256 good = 0x000000FF000100020003000400050006000700080009000a000b000c000d000e;
106          assertTrue(utils.isValidHatId(good));
107      }
108  
109      function testIsValidHatId_Invalid1() public {
110          uint256 empty1 = 0x000000FF000000020003000400050006000700080009000a000b000c000d000e;
111          uint256 empty2 = 0x000000FF000100000003000400050006000700080009000a000b000c000d000e;
112          uint256 empty3 = 0x000000FF000100020000000400050006000700080009000a000b000c000d000e;
113          uint256 empty4 = 0x000000FF000100020003000000050006000700080009000a000b000c000d000e;
114          uint256 empty5 = 0x000000FF000100020003000400000006000700080009000a000b000c000d000e;
115          uint256 empty6 = 0x000000FF000100020003000400050000000700080009000a000b000c000d000e;
116          uint256 empty7 = 0x000000FF000100020003000400050006000000080009000a000b000c000d000e;
117  
118          assertFalse(utils.isValidHatId(empty1));
119          assertFalse(utils.isValidHatId(empty2));
120          assertFalse(utils.isValidHatId(empty3));
121          assertFalse(utils.isValidHatId(empty4));
122          assertFalse(utils.isValidHatId(empty5));
123          assertFalse(utils.isValidHatId(empty6));
124          assertFalse(utils.isValidHatId(empty7));
125      }
126  
127      function testIsValidHatId_Invalid2() public {
128          uint256 empty8 = 0x000000FF000100020003000400050006000700000009000a000b000c000d000e;
129          uint256 empty9 = 0x000000FF000100020003000400050006000700080000000a000b000c000d000e;
130          uint256 emptya = 0x000000FF0001000200030004000500060007000800090000000b000c000d000e;
131          uint256 emptyb = 0x000000FF000100020003000400050006000700080009000a0000000c000d000e;
132          uint256 emptyc = 0x000000FF000100020003000400050006000700080009000a000b0000000d000e;
133          uint256 emptyd = 0x000000FF000100020003000400050006000700080009000a000b000c0000000e;
134          uint256 emptye = 0x000000FF000100020003000400050006000700080009000a000b000c000d0000;
135  
136          assertFalse(utils.isValidHatId(empty8));
137          assertFalse(utils.isValidHatId(empty9));
138          assertFalse(utils.isValidHatId(emptya));
139          assertFalse(utils.isValidHatId(emptyb));
140          assertFalse(utils.isValidHatId(emptyc));
141          assertFalse(utils.isValidHatId(emptyd));
142          // this is the same as a valid level 13 hat
143          assertTrue(utils.isValidHatId(emptye));
144      }
145  }