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 }