@rootzero/contracts 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/LICENSE +648 -0
  2. package/README.md +135 -0
  3. package/contracts/Blocks.sol +9 -0
  4. package/contracts/Commands.sol +41 -0
  5. package/contracts/Core.sol +10 -0
  6. package/contracts/Events.sol +18 -0
  7. package/contracts/Utils.sol +12 -0
  8. package/contracts/blocks/Blocks.sol +818 -0
  9. package/contracts/blocks/Keys.sol +24 -0
  10. package/contracts/blocks/Mem.sol +129 -0
  11. package/contracts/blocks/Schema.sol +105 -0
  12. package/contracts/blocks/Writers.sol +209 -0
  13. package/contracts/combinators/AmountToBalance.sol +25 -0
  14. package/contracts/combinators/AmountToCustody.sol +36 -0
  15. package/contracts/combinators/CustodyToBalance.sol +25 -0
  16. package/contracts/combinators/EachRoute.sol +18 -0
  17. package/contracts/combinators/MapBalance.sol +25 -0
  18. package/contracts/combinators/MapCustody.sol +25 -0
  19. package/contracts/combinators/RouteToBalance.sol +27 -0
  20. package/contracts/commands/Base.sol +40 -0
  21. package/contracts/commands/Borrow.sol +89 -0
  22. package/contracts/commands/Burn.sol +33 -0
  23. package/contracts/commands/Create.sol +32 -0
  24. package/contracts/commands/Credit.sol +36 -0
  25. package/contracts/commands/Debit.sol +46 -0
  26. package/contracts/commands/Deposit.sol +45 -0
  27. package/contracts/commands/Liquidate.sol +101 -0
  28. package/contracts/commands/Liquidity.sol +179 -0
  29. package/contracts/commands/Mint.sol +42 -0
  30. package/contracts/commands/Pipe.sol +55 -0
  31. package/contracts/commands/Provision.sol +73 -0
  32. package/contracts/commands/Reclaim.sol +48 -0
  33. package/contracts/commands/Redeem.sol +101 -0
  34. package/contracts/commands/Remove.sol +32 -0
  35. package/contracts/commands/Repay.sol +101 -0
  36. package/contracts/commands/Settle.sol +32 -0
  37. package/contracts/commands/Stake.sol +121 -0
  38. package/contracts/commands/Supply.sol +33 -0
  39. package/contracts/commands/Swap.sol +88 -0
  40. package/contracts/commands/Transfer.sol +44 -0
  41. package/contracts/commands/Unstake.sol +49 -0
  42. package/contracts/commands/Withdraw.sol +37 -0
  43. package/contracts/commands/admin/Allocate.sol +32 -0
  44. package/contracts/commands/admin/AllowAssets.sol +34 -0
  45. package/contracts/commands/admin/Authorize.sol +30 -0
  46. package/contracts/commands/admin/DenyAssets.sol +34 -0
  47. package/contracts/commands/admin/Destroy.sol +27 -0
  48. package/contracts/commands/admin/Init.sol +26 -0
  49. package/contracts/commands/admin/Relocate.sol +30 -0
  50. package/contracts/commands/admin/Unauthorize.sol +30 -0
  51. package/contracts/core/Access.sol +50 -0
  52. package/contracts/core/Balances.sol +23 -0
  53. package/contracts/core/Host.sol +25 -0
  54. package/contracts/core/Operation.sol +32 -0
  55. package/contracts/core/Validator.sol +31 -0
  56. package/contracts/events/Access.sol +14 -0
  57. package/contracts/events/Asset.sol +14 -0
  58. package/contracts/events/Balance.sol +14 -0
  59. package/contracts/events/Collateral.sol +15 -0
  60. package/contracts/events/Command.sol +14 -0
  61. package/contracts/events/Debt.sol +15 -0
  62. package/contracts/events/Deposit.sol +14 -0
  63. package/contracts/events/Emitter.sol +7 -0
  64. package/contracts/events/Governed.sol +14 -0
  65. package/contracts/events/HostAnnounced.sol +14 -0
  66. package/contracts/events/Listing.sol +14 -0
  67. package/contracts/events/Peer.sol +14 -0
  68. package/contracts/events/Quote.sol +14 -0
  69. package/contracts/events/RootZero.sol +14 -0
  70. package/contracts/events/Withdraw.sol +14 -0
  71. package/contracts/interfaces/IHostDiscovery.sol +6 -0
  72. package/contracts/peer/AllowAssets.sol +30 -0
  73. package/contracts/peer/Base.sol +17 -0
  74. package/contracts/peer/DenyAssets.sol +30 -0
  75. package/contracts/peer/Pull.sol +30 -0
  76. package/contracts/peer/Push.sol +30 -0
  77. package/contracts/test/TestBlockHelper.sol +261 -0
  78. package/contracts/test/TestBorrowHost.sol +47 -0
  79. package/contracts/test/TestBurnHost.sol +28 -0
  80. package/contracts/test/TestCreateHost.sol +26 -0
  81. package/contracts/test/TestDiscovery.sol +6 -0
  82. package/contracts/test/TestECDSA.sol +16 -0
  83. package/contracts/test/TestHost.sol +199 -0
  84. package/contracts/test/TestLiquidityHost.sol +145 -0
  85. package/contracts/test/TestMintHost.sol +40 -0
  86. package/contracts/test/TestPeerHost.sol +34 -0
  87. package/contracts/test/TestReclaimHost.sol +48 -0
  88. package/contracts/test/TestRejectEther.sol +8 -0
  89. package/contracts/test/TestRemoveHost.sol +26 -0
  90. package/contracts/test/TestSwapHost.sol +44 -0
  91. package/contracts/test/TestUtils.sol +169 -0
  92. package/contracts/test/TestValidator.sol +10 -0
  93. package/contracts/utils/Accounts.sol +40 -0
  94. package/contracts/utils/Assets.sol +76 -0
  95. package/contracts/utils/Channels.sol +11 -0
  96. package/contracts/utils/ECDSA.sol +36 -0
  97. package/contracts/utils/Ids.sol +75 -0
  98. package/contracts/utils/Layout.sol +22 -0
  99. package/contracts/utils/Utils.sol +126 -0
  100. package/contracts/utils/Value.sol +20 -0
  101. package/package.json +33 -0
@@ -0,0 +1,169 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { Accounts } from "../utils/Accounts.sol";
5
+ import { Amounts, Assets } from "../utils/Assets.sol";
6
+ import { Ids, Selectors } from "../utils/Ids.sol";
7
+ import { addrOr, applyBps, beforeBps, bytes32ToString, isFamily, isLocal, isLocalFamily, matchesBase, toLocalBase, toUnspecifiedBase, max8, max16, max32, max64, max128, max160 } from "../utils/Utils.sol";
8
+ import { Values } from "../utils/Value.sol";
9
+
10
+ contract TestUtils {
11
+ function testAddrOr(address addr, address or_) external pure returns (address) {
12
+ return addrOr(addr, or_);
13
+ }
14
+
15
+ function testToAdminAccount(address addr) external view returns (bytes32) {
16
+ return Accounts.toAdmin(addr);
17
+ }
18
+
19
+ function testToUserAccount(address addr) external pure returns (bytes32) {
20
+ return Accounts.toUser(addr);
21
+ }
22
+
23
+ function testAccountEvmAddr(bytes32 account) external pure returns (address) {
24
+ return Accounts.addrEvm(account);
25
+ }
26
+
27
+ function testIsAdminAccount(bytes32 account) external pure returns (bool) {
28
+ return Accounts.isAdmin(account);
29
+ }
30
+
31
+ function testToValueAsset() external view returns (bytes32) {
32
+ return Assets.toValue();
33
+ }
34
+
35
+ function testToErc20Asset(address addr) external view returns (bytes32) {
36
+ return Assets.toErc20(addr);
37
+ }
38
+
39
+ function testToErc721Asset(address addr) external view returns (bytes32) {
40
+ return Assets.toErc721(addr);
41
+ }
42
+
43
+ function testIsAsset32(bytes32 asset) external pure returns (bool) {
44
+ return Assets.is32(asset);
45
+ }
46
+
47
+ function testResolveAmount(uint available, uint min, uint max) external pure returns (uint) {
48
+ return Amounts.resolve(available, min, max);
49
+ }
50
+
51
+ function testEnsureAmount(uint amount) external pure returns (uint) {
52
+ return Amounts.ensure(amount);
53
+ }
54
+
55
+ function testEnsureAmountRange(uint amount, uint min, uint max) external pure returns (uint) {
56
+ return Amounts.ensure(amount, min, max);
57
+ }
58
+
59
+ function testEnsureAssetRef(bytes32 asset, bytes32 meta) external pure returns (bytes32) {
60
+ return Assets.ensureRef(asset, meta);
61
+ }
62
+
63
+ function testLocalErc20Addr(bytes32 asset) external view returns (address) {
64
+ return Assets.erc20Addr(asset);
65
+ }
66
+
67
+ function testLocalErc721Issuer(bytes32 asset) external view returns (address) {
68
+ return Assets.erc721Issuer(asset);
69
+ }
70
+
71
+ function testToHostId(address addr) external view returns (uint) {
72
+ return Ids.toHost(addr);
73
+ }
74
+
75
+ function testToCommandId(bytes32 name, address addr) external view returns (uint) {
76
+ return Ids.toCommand(Selectors.command(bytes32ToString(name)), addr);
77
+ }
78
+
79
+ function testToCommandSelector(bytes32 name) external pure returns (bytes4) {
80
+ return Selectors.command(bytes32ToString(name));
81
+ }
82
+
83
+ function testIsHost(uint id) external pure returns (bool) {
84
+ return Ids.isHost(id);
85
+ }
86
+
87
+ function testIsCommand(uint id) external pure returns (bool) {
88
+ return Ids.isCommand(id);
89
+ }
90
+
91
+ function testLocalNodeAddr(uint node) external view returns (address) {
92
+ return Ids.nodeAddr(node);
93
+ }
94
+
95
+ function testLocalHostAddr(uint host) external view returns (address) {
96
+ return Ids.hostAddr(host);
97
+ }
98
+
99
+ function testEnsureHost(uint id, address addr) external view returns (uint) {
100
+ return Ids.host(id, addr);
101
+ }
102
+
103
+ function testEnsureCommand(uint id) external pure returns (uint) {
104
+ return Ids.command(id);
105
+ }
106
+
107
+ function testApplyBps(uint amount, uint16 bps) external pure returns (uint) {
108
+ return applyBps(amount, bps);
109
+ }
110
+
111
+ function testBeforeBps(uint amount, uint16 bps) external pure returns (uint) {
112
+ return beforeBps(amount, bps);
113
+ }
114
+
115
+ function testIsFamily(uint value, uint24 family) external pure returns (bool) {
116
+ return isFamily(value, family);
117
+ }
118
+
119
+ function testIsLocal(uint value) external view returns (bool) {
120
+ return isLocal(value);
121
+ }
122
+
123
+ function testMatchesBase(bytes32 value, uint base) external pure returns (bool) {
124
+ return matchesBase(value, base);
125
+ }
126
+
127
+ function testToLocalBase(uint32 prefix) external view returns (uint) {
128
+ return toLocalBase(prefix);
129
+ }
130
+
131
+ function testMsgValue() external payable returns (uint) {
132
+ Values.Budget memory budget = Values.fromMsg();
133
+ return budget.remaining;
134
+ }
135
+
136
+ function testUseValue(uint amount, uint remaining) external pure returns (uint spent, uint remainingAfter) {
137
+ Values.Budget memory budget = Values.Budget({remaining: remaining});
138
+ spent = Values.use(budget, amount);
139
+ remainingAfter = budget.remaining;
140
+ }
141
+
142
+ function testBytes32ToString(bytes32 value) external pure returns (string memory) {
143
+ return bytes32ToString(value);
144
+ }
145
+
146
+ function testMax8(uint value) external pure returns (uint) {
147
+ return max8(value);
148
+ }
149
+
150
+ function testMax16(uint value) external pure returns (uint) {
151
+ return max16(value);
152
+ }
153
+
154
+ function testMax32(uint value) external pure returns (uint) {
155
+ return max32(value);
156
+ }
157
+
158
+ function testMax64(uint value) external pure returns (uint) {
159
+ return max64(value);
160
+ }
161
+
162
+ function testMax128(uint value) external pure returns (uint) {
163
+ return max128(value);
164
+ }
165
+
166
+ function testMax160(uint value) external pure returns (uint) {
167
+ return max160(value);
168
+ }
169
+ }
@@ -0,0 +1,10 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import { Validator } from "../core/Validator.sol";
5
+
6
+ contract TestValidator is Validator {
7
+ function testVerify(bytes32 hash, uint192 nonce, bytes calldata proof) external returns (address) {
8
+ return verify(hash, nonce, proof);
9
+ }
10
+ }
@@ -0,0 +1,40 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Layout} from "./Layout.sol";
5
+ import {isFamily, toLocalBase, toUnspecifiedBase} from "./Utils.sol";
6
+
7
+ library Accounts {
8
+ error InvalidAccount();
9
+
10
+ uint24 constant Family = (uint24(Layout.Evm32) << 8) | uint24(Layout.Account);
11
+ uint32 constant Admin = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Admin);
12
+ uint32 constant User = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.User);
13
+
14
+ function prefix(bytes32 account) internal pure returns (uint32) {
15
+ return uint32(uint(account) >> 224);
16
+ }
17
+
18
+ function isAdmin(bytes32 account) internal pure returns (bool) {
19
+ return prefix(account) == Admin;
20
+ }
21
+
22
+ function toAdmin(address addr) internal view returns (bytes32) {
23
+ return bytes32(toLocalBase(Admin) | (uint(uint160(addr)) << 32));
24
+ }
25
+
26
+ function toUser(address addr) internal pure returns (bytes32) {
27
+ return bytes32(toUnspecifiedBase(User) | (uint(uint160(addr)) << 32));
28
+ }
29
+
30
+ function ensureEvm(bytes32 account) internal pure returns (bytes32) {
31
+ if (!isFamily(uint(account), Family)) {
32
+ revert InvalidAccount();
33
+ }
34
+ return account;
35
+ }
36
+
37
+ function addrEvm(bytes32 account) internal pure returns (address) {
38
+ return address(uint160(uint(ensureEvm(account)) >> 32));
39
+ }
40
+ }
@@ -0,0 +1,76 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Layout} from "./Layout.sol";
5
+ import {matchesBase, toLocalBase} from "./Utils.sol";
6
+
7
+ library Assets {
8
+ error InvalidAsset();
9
+
10
+ uint32 constant Value = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Value);
11
+ uint32 constant Erc20 = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Erc20);
12
+ uint32 constant Erc721 = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Erc721);
13
+
14
+ function is32(bytes32 asset) internal pure returns (bool) {
15
+ return bytes1(asset) == 0x20;
16
+ }
17
+
18
+ function toValue() internal view returns (bytes32) {
19
+ return bytes32(toLocalBase(Value));
20
+ }
21
+
22
+ function toErc20(address addr) internal view returns (bytes32) {
23
+ return bytes32(toLocalBase(Erc20) | (uint(uint160(addr)) << 32));
24
+ }
25
+
26
+ function toErc721(address issuer) internal view returns (bytes32) {
27
+ return bytes32(toLocalBase(Erc721) | (uint(uint160(issuer)) << 32));
28
+ }
29
+
30
+ function ensureRef(bytes32 asset, bytes32 meta) internal pure returns (bytes32) {
31
+ if (asset == 0 || (bytes1(asset) == 0x20 && meta != 0)) revert InvalidAsset();
32
+ return bytes1(asset) == 0x20 ? asset : keccak256(bytes.concat(asset, meta));
33
+ }
34
+
35
+ function erc20Addr(bytes32 asset) internal view returns (address) {
36
+ if (!matchesBase(asset, toLocalBase(Erc20))) revert InvalidAsset();
37
+ return address(uint160(uint(asset) >> 32));
38
+ }
39
+
40
+ function erc721Issuer(bytes32 asset) internal view returns (address) {
41
+ if (!matchesBase(asset, toLocalBase(Erc721))) revert InvalidAsset();
42
+ return address(uint160(uint(asset) >> 32));
43
+ }
44
+ }
45
+
46
+ library Amounts {
47
+ error ZeroAmount();
48
+ error BadAmount(uint amount);
49
+
50
+ function ensure(uint amount) internal pure returns (uint) {
51
+ if (amount == 0) {
52
+ revert ZeroAmount();
53
+ }
54
+ return amount;
55
+ }
56
+
57
+ function ensure(uint amount, uint min, uint max) internal pure returns (uint) {
58
+ if (amount < min || amount > max) {
59
+ revert BadAmount(amount);
60
+ }
61
+ return amount;
62
+ }
63
+
64
+ function ensureRef(bytes32 asset, bytes32 meta, uint amount) internal pure returns (bytes32 ref) {
65
+ ensure(amount);
66
+ return Assets.ensureRef(asset, meta);
67
+ }
68
+
69
+ function resolve(uint available, uint min, uint max) internal pure returns (uint) {
70
+ uint amount = available > max ? max : available;
71
+ if (amount < min) {
72
+ revert BadAmount(amount);
73
+ }
74
+ return amount;
75
+ }
76
+ }
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ library Channels {
5
+ uint8 constant Setup = 0x0001;
6
+ uint8 constant Steps = 0x0002;
7
+ uint8 constant Balances = 0x0003;
8
+ uint8 constant Transactions = 0x0004;
9
+ uint8 constant Custodies = 0x0005;
10
+ uint8 constant Claims = 0x0006;
11
+ }
@@ -0,0 +1,36 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ library ECDSA {
5
+ uint256 internal constant MALLEABILITY_THRESHOLD =
6
+ 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0;
7
+
8
+ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 digest) {
9
+ assembly ("memory-safe") {
10
+ mstore(0x00, "\x19Ethereum Signed Message:\n32")
11
+ mstore(0x1c, hash)
12
+ digest := keccak256(0x00, 0x3c)
13
+ }
14
+ }
15
+
16
+ function tryRecoverCalldata(bytes32 hash, bytes calldata signature) internal pure returns (address signer) {
17
+ if (signature.length != 65) return address(0);
18
+
19
+ bytes32 r;
20
+ bytes32 s;
21
+ uint8 v;
22
+
23
+ assembly ("memory-safe") {
24
+ let offset := signature.offset
25
+ r := calldataload(offset)
26
+ s := calldataload(add(offset, 0x20))
27
+ v := byte(0, calldataload(add(offset, 0x40)))
28
+ }
29
+
30
+ if (v < 27) v += 27;
31
+ if (v != 27 && v != 28) return address(0);
32
+ if (uint256(s) > MALLEABILITY_THRESHOLD) return address(0);
33
+
34
+ return ecrecover(hash, v, r, s);
35
+ }
36
+ }
@@ -0,0 +1,75 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {Layout} from "./Layout.sol";
5
+ import {isLocalFamily, matchesBase, toLocalBase} from "./Utils.sol";
6
+
7
+ library Ids {
8
+ error InvalidId();
9
+
10
+ uint24 constant Node = (uint24(Layout.Evm32) << 8) | uint24(Layout.Node);
11
+ uint32 constant Host = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Host);
12
+ uint32 constant Command = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Command);
13
+ uint32 constant Peer = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Node) << 8) | uint32(Layout.Peer);
14
+
15
+ function isHost(uint id) internal pure returns (bool) {
16
+ return uint32(id >> 224) == Host;
17
+ }
18
+
19
+ function isCommand(uint id) internal pure returns (bool) {
20
+ return uint32(id >> 224) == Command;
21
+ }
22
+
23
+ function isPeer(uint id) internal pure returns (bool) {
24
+ return uint32(id >> 224) == Peer;
25
+ }
26
+
27
+ function command(uint id) internal pure returns (uint cid) {
28
+ if (!isCommand(id)) revert InvalidId();
29
+ return id;
30
+ }
31
+
32
+ function host(uint id, address target) internal view returns (uint hid) {
33
+ if (id != toHost(target)) revert InvalidId();
34
+ return id;
35
+ }
36
+
37
+ function toHost(address target) internal view returns (uint) {
38
+ return toLocalBase(Host) | uint(uint160(target));
39
+ }
40
+
41
+ function toCommand(bytes4 selector, address target) internal view returns (uint) {
42
+ uint id = toLocalBase(Command) | uint(uint160(target));
43
+ id |= uint(uint32(selector)) << 160;
44
+ return id;
45
+ }
46
+
47
+ function toPeer(bytes4 selector, address target) internal view returns (uint) {
48
+ uint id = toLocalBase(Peer) | uint(uint160(target));
49
+ id |= uint(uint32(selector)) << 160;
50
+ return id;
51
+ }
52
+
53
+ function nodeAddr(uint id) internal view returns (address) {
54
+ if (!isLocalFamily(id, Node)) revert InvalidId();
55
+ return address(uint160(id));
56
+ }
57
+
58
+ function hostAddr(uint id) internal view returns (address) {
59
+ if (!matchesBase(bytes32(id), toLocalBase(Host))) revert InvalidId();
60
+ return address(uint160(id));
61
+ }
62
+ }
63
+
64
+ library Selectors {
65
+ string constant CommandArgs = "((uint256,bytes32,bytes,bytes))";
66
+ string constant PeerArgs = "(bytes)";
67
+
68
+ function command(string memory name) internal pure returns (bytes4) {
69
+ return bytes4(keccak256(bytes.concat(bytes(name), bytes(CommandArgs))));
70
+ }
71
+
72
+ function peer(string memory name) internal pure returns (bytes4) {
73
+ return bytes4(keccak256(bytes.concat(bytes(name), bytes(PeerArgs))));
74
+ }
75
+ }
@@ -0,0 +1,22 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ library Layout {
5
+ uint16 constant Evm32 = 0x2001;
6
+ uint16 constant Evm64 = 0x4001;
7
+
8
+ uint8 constant Account = 0x01;
9
+ uint8 constant Node = 0x02;
10
+ uint8 constant Asset = 0x03;
11
+
12
+ uint8 constant Admin = 0x01;
13
+ uint8 constant User = 0x02;
14
+
15
+ uint8 constant Host = 0x01;
16
+ uint8 constant Command = 0x02;
17
+ uint8 constant Peer = 0x03;
18
+
19
+ uint8 constant Value = 0x01;
20
+ uint8 constant Erc20 = 0x02;
21
+ uint8 constant Erc721 = 0x03;
22
+ }
@@ -0,0 +1,126 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ uint16 constant MAX_BPS = 10_000;
5
+
6
+ error ValueOverflow();
7
+
8
+ function max8(uint value) pure returns (uint) {
9
+ if (value > type(uint8).max) {
10
+ revert ValueOverflow();
11
+ }
12
+ return value;
13
+ }
14
+
15
+ function max16(uint value) pure returns (uint) {
16
+ if (value > type(uint16).max) {
17
+ revert ValueOverflow();
18
+ }
19
+ return value;
20
+ }
21
+
22
+ function max24(uint value) pure returns (uint) {
23
+ if (value > type(uint24).max) {
24
+ revert ValueOverflow();
25
+ }
26
+ return value;
27
+ }
28
+
29
+ function max32(uint value) pure returns (uint) {
30
+ if (value > type(uint32).max) {
31
+ revert ValueOverflow();
32
+ }
33
+ return value;
34
+ }
35
+
36
+ function max40(uint value) pure returns (uint) {
37
+ if (value > type(uint40).max) {
38
+ revert ValueOverflow();
39
+ }
40
+ return value;
41
+ }
42
+
43
+ function max64(uint value) pure returns (uint) {
44
+ if (value > type(uint64).max) {
45
+ revert ValueOverflow();
46
+ }
47
+ return value;
48
+ }
49
+
50
+ function max96(uint value) pure returns (uint) {
51
+ if (value > type(uint96).max) {
52
+ revert ValueOverflow();
53
+ }
54
+ return value;
55
+ }
56
+
57
+ function max128(uint value) pure returns (uint) {
58
+ if (value > type(uint128).max) {
59
+ revert ValueOverflow();
60
+ }
61
+ return value;
62
+ }
63
+
64
+ function max160(uint value) pure returns (uint) {
65
+ if (value > type(uint160).max) {
66
+ revert ValueOverflow();
67
+ }
68
+ return value;
69
+ }
70
+
71
+ function addrOr(address addr, address or) pure returns (address) {
72
+ return addr == address(0) ? or : addr;
73
+ }
74
+
75
+ function bytes32ToString(bytes32 value) pure returns (string memory result) {
76
+ uint len;
77
+ while (len < 32 && value[len] != 0) {
78
+ unchecked {
79
+ ++len;
80
+ }
81
+ }
82
+
83
+ result = new string(len);
84
+ assembly ("memory-safe") {
85
+ mstore(add(result, 0x20), value)
86
+ }
87
+ }
88
+
89
+ function toLocalBase(uint32 prefix) view returns (uint) {
90
+ return (uint(prefix) << 224) | (uint(max32(block.chainid)) << 192);
91
+ }
92
+
93
+ function toLocalFamily(uint24 family) view returns (uint) {
94
+ return (uint(family) << 232) | (uint(max32(block.chainid)) << 192);
95
+ }
96
+
97
+ function toUnspecifiedBase(uint32 prefix) pure returns (uint) {
98
+ return uint(prefix) << 224;
99
+ }
100
+
101
+ function isFamily(uint value, uint24 family) pure returns (bool) {
102
+ return uint24(value >> 232) == family;
103
+ }
104
+
105
+ function isLocal(uint value) view returns (bool) {
106
+ return uint32(value >> 192) == block.chainid;
107
+ }
108
+
109
+ function isLocalFamily(uint value, uint24 family) view returns (bool) {
110
+ return isFamily(value, family) && isLocal(value);
111
+ }
112
+
113
+ function matchesBase(bytes32 value, uint base) pure returns (bool) {
114
+ return uint64(uint(value) >> 192) == uint64(base >> 192);
115
+ }
116
+
117
+ function applyBps(uint amount, uint16 bps) pure returns (uint) {
118
+ if (amount == 0 || bps == 0) return 0;
119
+ return (amount * bps) / MAX_BPS;
120
+ }
121
+
122
+ function beforeBps(uint amount, uint16 bps) pure returns (uint) {
123
+ if (amount == 0 || bps == 0) return 0;
124
+ return (amount * MAX_BPS) / (MAX_BPS + bps);
125
+ }
126
+
@@ -0,0 +1,20 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ library Values {
5
+ error InsufficientValue();
6
+
7
+ struct Budget {
8
+ uint remaining;
9
+ }
10
+
11
+ function fromMsg() internal view returns (Budget memory) {
12
+ return Budget({remaining: msg.value});
13
+ }
14
+
15
+ function use(Budget memory budget, uint amount) internal pure returns (uint) {
16
+ if (amount > budget.remaining) revert InsufficientValue();
17
+ budget.remaining -= amount;
18
+ return amount;
19
+ }
20
+ }
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@rootzero/contracts",
3
+ "version": "0.2.0",
4
+ "description": "Solidity contracts and protocol building blocks for RootZero hosts and commands.",
5
+ "private": false,
6
+ "license": "GPL-3.0-only",
7
+ "type": "module",
8
+ "files": [
9
+ "*.sol",
10
+ "contracts/**/*.sol",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "scripts": {
18
+ "compile": "hardhat compile",
19
+ "test": "hardhat test",
20
+ "prepublishOnly": "npm test",
21
+ "prepare:package": "node scripts/prepare-package.mjs",
22
+ "pack:package": "npm run prepare:package && npm pack ./dist/package",
23
+ "publish:package": "npm test && npm run prepare:package && npm publish ./dist/package --access public"
24
+ },
25
+ "devDependencies": {
26
+ "@nomicfoundation/hardhat-mocha": "^3.0.13",
27
+ "chai": "^6.2.2",
28
+ "ethers": "^6.16.0",
29
+ "hardhat": "^3.1.7",
30
+ "mocha": "^11.7.5",
31
+ "typescript": "~5.8.0"
32
+ }
33
+ }