@rootzero/contracts 1.4.0 → 1.6.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 (68) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/Core.sol +4 -2
  3. package/Endpoints.sol +5 -3
  4. package/Events.sol +2 -1
  5. package/README.md +58 -31
  6. package/Utils.sol +4 -3
  7. package/blocks/Cursors.sol +107 -143
  8. package/blocks/Keys.sol +15 -15
  9. package/blocks/Schema.sol +27 -28
  10. package/blocks/Writers.sol +26 -33
  11. package/commands/Base.sol +2 -2
  12. package/commands/Burn.sol +3 -4
  13. package/commands/Credit.sol +3 -4
  14. package/commands/Debit.sol +4 -5
  15. package/commands/Deposit.sol +8 -10
  16. package/commands/Payout.sol +3 -6
  17. package/commands/Withdraw.sol +3 -4
  18. package/commands/admin/AllowAssets.sol +7 -9
  19. package/commands/admin/Allowance.sol +5 -7
  20. package/commands/admin/Appoint.sol +2 -3
  21. package/commands/admin/Authorize.sol +2 -3
  22. package/commands/admin/Base.sol +9 -0
  23. package/commands/admin/DenyAssets.sol +7 -9
  24. package/commands/admin/Destroy.sol +2 -3
  25. package/commands/admin/Dismiss.sol +2 -3
  26. package/commands/admin/Execute.sol +4 -5
  27. package/commands/admin/Init.sol +2 -3
  28. package/commands/admin/Label.sol +2 -3
  29. package/commands/admin/Unauthorize.sol +2 -3
  30. package/core/Access.sol +2 -2
  31. package/core/Balances.sol +10 -11
  32. package/core/Calls.sol +7 -7
  33. package/core/Commitments.sol +19 -0
  34. package/core/Escrows.sol +34 -0
  35. package/core/Host.sol +2 -2
  36. package/core/Runtime.sol +11 -6
  37. package/core/Types.sol +0 -14
  38. package/docs/Schema.md +29 -10
  39. package/events/Asset.sol +17 -3
  40. package/events/Balance.sol +2 -3
  41. package/events/Commitment.sol +19 -0
  42. package/events/Locked.sol +2 -3
  43. package/events/Position.sol +2 -3
  44. package/events/Received.sol +2 -3
  45. package/events/Spent.sol +2 -3
  46. package/events/Unlocked.sol +2 -3
  47. package/guards/Base.sol +4 -4
  48. package/package.json +1 -1
  49. package/peer/AllowAssets.sol +3 -3
  50. package/peer/Allowance.sol +2 -2
  51. package/peer/Base.sol +4 -4
  52. package/peer/Credit.sol +10 -10
  53. package/peer/Debit.sol +10 -10
  54. package/peer/DenyAssets.sol +3 -3
  55. package/peer/Recover.sol +51 -0
  56. package/peer/Redeem.sol +48 -0
  57. package/peer/Settle.sol +3 -3
  58. package/queries/Assets.sol +7 -8
  59. package/queries/Balances.sol +8 -9
  60. package/queries/Base.sol +4 -4
  61. package/queries/Positions.sol +4 -6
  62. package/utils/Accounts.sol +76 -58
  63. package/utils/Assets.sol +55 -115
  64. package/utils/Ids.sol +33 -233
  65. package/utils/Layout.sol +11 -17
  66. package/utils/Nodes.sol +263 -0
  67. package/utils/Utils.sol +9 -24
  68. package/peer/BalancePull.sol +0 -49
@@ -2,7 +2,8 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {Layout} from "./Layout.sol";
5
- import {isFamily, toLocalBase, toUnspecifiedBase} from "./Utils.sol";
5
+ import {Ids} from "./Ids.sol";
6
+ import {ensureAddr, isFamily, toLocalBase, toUnspecifiedBase} from "./Utils.sol";
6
7
 
7
8
  /// @title Accounts
8
9
  /// @notice Encoding and decoding helpers for 256-bit account identifiers.
@@ -11,18 +12,24 @@ import {isFamily, toLocalBase, toUnspecifiedBase} from "./Utils.sol";
11
12
  /// - `Admin` — chain-local EVM address in bits [191:32]
12
13
  /// - `Guardian` — chain-local EVM address in bits [191:32]
13
14
  /// - `User` — chain-agnostic EVM address in bits [191:32]
15
+ ///
16
+ /// If the first byte is zero, the account is an opaque
17
+ /// `0x00 || bytes31(hash)` ID. The full account identity must be supplied by
18
+ /// lookup or witness data when native account metadata is needed.
19
+ ///
20
+ /// The helpers in this library validate and deconstruct structured account IDs.
14
21
  library Accounts {
15
22
  /// @dev Thrown when an account ID does not belong to the EVM family.
16
23
  error InvalidAccount();
17
24
 
18
25
  /// @dev 24-bit family tag shared by all EVM-backed account types.
19
- uint24 constant Family = (uint24(Layout.Evm32) << 8) | uint24(Layout.Account);
26
+ uint24 constant Family = (uint24(Layout.Evm) << 8) | uint24(Layout.Account);
20
27
  /// @dev Full 4-byte type prefix for admin accounts (chain-local EVM address).
21
- uint32 constant Admin = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Admin);
28
+ uint32 constant Admin = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Admin);
22
29
  /// @dev Full 4-byte type prefix for guardian accounts (chain-local EVM address).
23
- uint32 constant Guardian = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Guardian);
30
+ uint32 constant Guardian = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.Guardian);
24
31
  /// @dev Full 4-byte type prefix for user accounts (chain-agnostic EVM address).
25
- uint32 constant User = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.User);
32
+ uint32 constant User = (uint32(Layout.Evm) << 16) | (uint32(Layout.Account) << 8) | uint32(Layout.User);
26
33
 
27
34
  /// @notice Extract the 4-byte type prefix from an account ID.
28
35
  /// @param account Account identifier.
@@ -31,9 +38,14 @@ library Accounts {
31
38
  return uint32(uint(account) >> 224);
32
39
  }
33
40
 
34
- /// @notice Return true if `account` uses the Account category tag in the type field.
35
- function isAccount(bytes32 account) internal pure returns (bool) {
36
- return uint8(uint(account) >> 232) == Layout.Account;
41
+ /// @notice Return true if `account` belongs to the EVM account family.
42
+ function isEvm(bytes32 account) internal pure returns (bool) {
43
+ return isFamily(uint(account), Family);
44
+ }
45
+
46
+ /// @notice Return true if `account` is opaque.
47
+ function isOpaque(bytes32 account) internal pure returns (bool) {
48
+ return Ids.isOpaque(account);
37
49
  }
38
50
 
39
51
  /// @notice Return true if `account` is an admin account.
@@ -51,82 +63,88 @@ library Accounts {
51
63
  return prefix(account) == User;
52
64
  }
53
65
 
54
- /// @notice Assert that `input` is an account and return it unchanged.
55
- /// @param input Account identifier to validate.
56
- /// @return account The same `input` if it is an account.
57
- function ensure(bytes32 input) internal pure returns (bytes32 account) {
58
- if (!isAccount(input)) revert InvalidAccount();
59
- return input;
66
+ /// @notice Assert that `value` belongs to the EVM account family and return it unchanged.
67
+ /// @param value Account identifier to validate.
68
+ /// @return account The same `value` if it is an EVM account.
69
+ function evm(bytes32 value) internal pure returns (bytes32 account) {
70
+ if (!isEvm(value)) revert InvalidAccount();
71
+ return value;
60
72
  }
61
73
 
62
- /// @notice Assert that `input` is an admin account and return it unchanged.
63
- /// @param input Account identifier to validate.
64
- /// @return account The same `input` if it is an admin account.
65
- function admin(bytes32 input) internal pure returns (bytes32 account) {
66
- if (!isAdmin(input)) revert InvalidAccount();
67
- return input;
74
+ /// @notice Assert that `value` is an opaque account and return it unchanged.
75
+ /// @param value Account identifier to validate.
76
+ /// @return account The same `value` if it is opaque.
77
+ function opaque(bytes32 value) internal pure returns (bytes32 account) {
78
+ if (!Ids.isOpaque(value)) revert InvalidAccount();
79
+ return value;
68
80
  }
69
81
 
70
- /// @notice Assert that `input` is a guardian account and return it unchanged.
71
- /// @param input Account identifier to validate.
72
- /// @return account The same `input` if it is a guardian account.
73
- function guardian(bytes32 input) internal pure returns (bytes32 account) {
74
- if (!isGuardian(input)) revert InvalidAccount();
75
- return input;
82
+ /// @notice Assert that `value` is an admin account and return it unchanged.
83
+ /// @param value Account identifier to validate.
84
+ /// @return account The same `value` if it is an admin account.
85
+ function admin(bytes32 value) internal pure returns (bytes32 account) {
86
+ if (!isAdmin(value)) revert InvalidAccount();
87
+ return value;
76
88
  }
77
89
 
78
- /// @notice Assert that `input` is a user account and return it unchanged.
79
- /// @param input Account identifier to validate.
80
- /// @return account The same `input` if it is a user account.
81
- function user(bytes32 input) internal pure returns (bytes32 account) {
82
- if (!isUser(input)) revert InvalidAccount();
83
- return input;
90
+ /// @notice Assert that `value` is a guardian account and return it unchanged.
91
+ /// @param value Account identifier to validate.
92
+ /// @return account The same `value` if it is a guardian account.
93
+ function guardian(bytes32 value) internal pure returns (bytes32 account) {
94
+ if (!isGuardian(value)) revert InvalidAccount();
95
+ return value;
96
+ }
97
+
98
+ /// @notice Assert that `value` is a user account and return it unchanged.
99
+ /// @param value Account identifier to validate.
100
+ /// @return account The same `value` if it is a user account.
101
+ function user(bytes32 value) internal pure returns (bytes32 account) {
102
+ if (!isUser(value)) revert InvalidAccount();
103
+ return value;
84
104
  }
85
105
 
86
106
  /// @notice Encode an EVM address as a chain-local admin account ID.
87
- /// @param addr EVM address to embed.
107
+ /// @param account EVM address to embed.
88
108
  /// @return Admin account ID bound to the current chain.
89
- function toAdmin(address addr) internal view returns (bytes32) {
90
- return bytes32(toLocalBase(Admin) | (uint(uint160(addr)) << 32));
109
+ function toAdmin(address account) internal view returns (bytes32) {
110
+ return bytes32(toLocalBase(Admin) | (uint(uint160(account)) << 32));
91
111
  }
92
112
 
93
113
  /// @notice Encode an EVM address as a chain-local guardian account ID.
94
- /// @param addr EVM address to embed.
114
+ /// @param account EVM address to embed.
95
115
  /// @return Guardian account ID bound to the current chain.
96
- function toGuardian(address addr) internal view returns (bytes32) {
97
- return bytes32(toLocalBase(Guardian) | (uint(uint160(addr)) << 32));
116
+ function toGuardian(address account) internal view returns (bytes32) {
117
+ return bytes32(toLocalBase(Guardian) | (uint(uint160(account)) << 32));
98
118
  }
99
119
 
100
120
  /// @notice Encode an EVM address as a chain-agnostic user account ID.
101
- /// @param addr EVM address to embed.
121
+ /// @param account EVM address to embed.
102
122
  /// @return User account ID without a chain binding.
103
- function toUser(address addr) internal pure returns (bytes32) {
104
- return bytes32(toUnspecifiedBase(User) | (uint(uint160(addr)) << 32));
123
+ function toUser(address account) internal pure returns (bytes32) {
124
+ return bytes32(toUnspecifiedBase(User) | (uint(uint160(account)) << 32));
105
125
  }
106
126
 
107
- /// @notice Assert that `account` belongs to the EVM account family and return it unchanged.
108
- /// @param account Account ID to validate.
109
- /// @return The same `account` value if valid.
110
- function ensureEvm(bytes32 account) internal pure returns (bytes32) {
111
- if (!isFamily(uint(account), Family)) {
112
- revert InvalidAccount();
113
- }
114
- return account;
127
+ /// @notice Derive an opaque account ID from a keccak preimage.
128
+ /// @param preimage Preimage whose first byte is `0x01`.
129
+ /// @return account `0x00 || bytes31(keccak256(preimage))`.
130
+ function toKeccak(bytes memory preimage) internal pure returns (bytes32 account) {
131
+ return Ids.toKeccak(preimage);
115
132
  }
116
133
 
117
- /// @notice Assert that `account` is not an admin account and return it unchanged.
118
- /// @param account Account ID to validate.
119
- /// @return The same `account` value if valid.
120
- function ensureNotAdmin(bytes32 account) internal pure returns (bytes32) {
121
- if (isAdmin(account)) revert InvalidAccount();
134
+ /// @notice Assert that `account` matches the opaque keccak ID for `preimage`.
135
+ /// @param account Opaque account ID to validate.
136
+ /// @param preimage Preimage whose first byte is `0x01`.
137
+ /// @return The same `account` value if it matches.
138
+ function matchKeccak(bytes32 account, bytes memory preimage) internal pure returns (bytes32) {
139
+ if (account != Ids.toKeccak(preimage)) revert InvalidAccount();
122
140
  return account;
123
141
  }
124
142
 
125
- /// @notice Extract the EVM address embedded in an EVM-family account ID.
143
+ /// @notice Extract the address embedded in an EVM-family account ID.
126
144
  /// Reverts if `account` is not an EVM-family account.
127
145
  /// @param account EVM-family account ID.
128
- /// @return Embedded EVM address (bits [191:32] of the ID).
129
- function addrEvm(bytes32 account) internal pure returns (address) {
130
- return address(uint160(uint(ensureEvm(account)) >> 32));
146
+ /// @return Embedded address (bits [191:32] of the ID).
147
+ function addr(bytes32 account) internal pure returns (address) {
148
+ return ensureAddr(address(uint160(uint(evm(account)) >> 32)));
131
149
  }
132
150
  }
package/utils/Assets.sol CHANGED
@@ -2,7 +2,8 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {Layout} from "./Layout.sol";
5
- import {matchesBase, toLocalBase} from "./Utils.sol";
5
+ import {Ids} from "./Ids.sol";
6
+ import {ensureAddr, isFamily, matchesBase, toLocalBase} from "./Utils.sol";
6
7
 
7
8
  /// @title Assets
8
9
  /// @notice Encoding and decoding helpers for 256-bit asset identifiers.
@@ -10,8 +11,12 @@ import {matchesBase, toLocalBase} from "./Utils.sol";
10
11
  /// Asset IDs embed a 4-byte type tag in bits [255:224]:
11
12
  /// - `Native` - native chain coin/token; no address payload
12
13
  /// - `Erc20` - ERC-20 token; contract address in bits [191:32]
13
- /// - `Erc721` - ERC-721 collection; collection address in bits [191:32]
14
- /// - `Erc1155` - ERC-1155 collection; collection address in bits [191:32]
14
+ ///
15
+ /// If the first byte is zero, the asset is an opaque
16
+ /// `0x00 || bytes31(hash)` ID. The full asset metadata must be supplied by
17
+ /// lookup or witness data when native token handling needs it.
18
+ ///
19
+ /// The helpers in this library validate and deconstruct structured asset IDs.
15
20
  ///
16
21
  /// All asset IDs are chain-local (include `block.chainid` in bits [223:192]).
17
22
  library Assets {
@@ -20,28 +25,21 @@ library Assets {
20
25
  /// @dev Thrown when an asset is not authorized for the requested operation.
21
26
  error UnauthorizedAsset();
22
27
 
28
+ /// @dev 24-bit family tag shared by all EVM-backed asset types.
29
+ uint24 constant Family = (uint24(Layout.Evm) << 8) | uint24(Layout.Asset);
23
30
  /// @dev Full 4-byte type prefix for the native chain coin/token asset.
24
- uint32 constant Native = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Native);
31
+ uint32 constant Native = (uint32(Layout.Evm) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Native);
25
32
  /// @dev Full 4-byte type prefix for ERC-20 assets.
26
- uint32 constant Erc20 = (uint32(Layout.Evm32) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Erc20);
27
- /// @dev Full 4-byte type prefix for ERC-721 assets.
28
- uint32 constant Erc721 = (uint32(Layout.Evm64) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Erc721);
29
- /// @dev Full 4-byte type prefix for ERC-1155 assets.
30
- uint32 constant Erc1155 = (uint32(Layout.Evm64) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Erc1155);
31
-
32
- /// @notice Return true if `asset` uses the Asset category tag in the type field.
33
- function isAsset(bytes32 asset) internal pure returns (bool) {
34
- return uint8(uint(asset) >> 232) == Layout.Asset;
35
- }
33
+ uint32 constant Erc20 = (uint32(Layout.Evm) << 16) | (uint32(Layout.Asset) << 8) | uint32(Layout.Erc20);
36
34
 
37
- /// @notice Return true if `asset` uses a 32-byte asset layout with no metadata identity.
38
- function is32(bytes32 asset) internal pure returns (bool) {
39
- return isAsset(asset) && uint8(uint(asset) >> 240) == Layout.Width32;
35
+ /// @notice Return true if `asset` belongs to the EVM asset family.
36
+ function isEvm(bytes32 asset) internal pure returns (bool) {
37
+ return isFamily(uint(asset), Family);
40
38
  }
41
39
 
42
- /// @notice Return true if `asset` uses a 64-byte asset layout with metadata-backed identity.
43
- function is64(bytes32 asset) internal pure returns (bool) {
44
- return isAsset(asset) && uint8(uint(asset) >> 240) == Layout.Width64;
40
+ /// @notice Return true if `asset` is opaque.
41
+ function isOpaque(bytes32 asset) internal pure returns (bool) {
42
+ return Ids.isOpaque(asset);
45
43
  }
46
44
 
47
45
  /// @notice Return true if `asset` is the local native chain coin/token asset.
@@ -54,46 +52,36 @@ library Assets {
54
52
  return matchesBase(asset, toLocalBase(Erc20));
55
53
  }
56
54
 
57
- /// @notice Return true if `asset` is a local ERC-721 asset.
58
- function isErc721(bytes32 asset) internal view returns (bool) {
59
- return matchesBase(asset, toLocalBase(Erc721));
60
- }
61
-
62
- /// @notice Return true if `asset` is a local ERC-1155 asset.
63
- function isErc1155(bytes32 asset) internal view returns (bool) {
64
- return matchesBase(asset, toLocalBase(Erc1155));
55
+ /// @notice Assert that `value` belongs to the EVM asset family and return it unchanged.
56
+ /// @param value Asset identifier to validate.
57
+ /// @return asset The same `value` if it is an EVM asset.
58
+ function evm(bytes32 value) internal pure returns (bytes32 asset) {
59
+ if (!isEvm(value)) revert InvalidAsset();
60
+ return value;
65
61
  }
66
62
 
67
- /// @notice Assert that `input` is the local native chain coin/token asset and return it unchanged.
68
- /// @param input Asset identifier to validate.
69
- /// @return asset The same `input` if it is the local native asset.
70
- function native(bytes32 input) internal view returns (bytes32 asset) {
71
- if (!isNative(input)) revert InvalidAsset();
72
- return input;
63
+ /// @notice Assert that `value` is an opaque asset and return it unchanged.
64
+ /// @param value Asset identifier to validate.
65
+ /// @return asset The same `value` if it is opaque.
66
+ function opaque(bytes32 value) internal pure returns (bytes32 asset) {
67
+ if (!Ids.isOpaque(value)) revert InvalidAsset();
68
+ return value;
73
69
  }
74
70
 
75
- /// @notice Assert that `input` is a local ERC-20 asset and return it unchanged.
76
- /// @param input Asset identifier to validate.
77
- /// @return asset The same `input` if it is a local ERC-20 asset.
78
- function erc20(bytes32 input) internal view returns (bytes32 asset) {
79
- if (!isErc20(input)) revert InvalidAsset();
80
- return input;
71
+ /// @notice Assert that `value` is the local native chain coin/token asset and return it unchanged.
72
+ /// @param value Asset identifier to validate.
73
+ /// @return asset The same `value` if it is the local native asset.
74
+ function native(bytes32 value) internal view returns (bytes32 asset) {
75
+ if (!isNative(value)) revert InvalidAsset();
76
+ return value;
81
77
  }
82
78
 
83
- /// @notice Assert that `input` is a local ERC-721 asset and return it unchanged.
84
- /// @param input Asset identifier to validate.
85
- /// @return asset The same `input` if it is a local ERC-721 asset.
86
- function erc721(bytes32 input) internal view returns (bytes32 asset) {
87
- if (!isErc721(input)) revert InvalidAsset();
88
- return input;
89
- }
90
-
91
- /// @notice Assert that `input` is a local ERC-1155 asset and return it unchanged.
92
- /// @param input Asset identifier to validate.
93
- /// @return asset The same `input` if it is a local ERC-1155 asset.
94
- function erc1155(bytes32 input) internal view returns (bytes32 asset) {
95
- if (!isErc1155(input)) revert InvalidAsset();
96
- return input;
79
+ /// @notice Assert that `value` is a local ERC-20 asset and return it unchanged.
80
+ /// @param value Asset identifier to validate.
81
+ /// @return asset The same `value` if it is a local ERC-20 asset.
82
+ function erc20(bytes32 value) internal view returns (bytes32 asset) {
83
+ if (!isErc20(value)) revert InvalidAsset();
84
+ return value;
97
85
  }
98
86
 
99
87
  /// @notice Create a chain-local native coin/token asset ID.
@@ -109,18 +97,20 @@ library Assets {
109
97
  return bytes32(toLocalBase(Erc20) | (uint(uint160(addr)) << 32));
110
98
  }
111
99
 
112
- /// @notice Create a chain-local ERC-721 asset ID for `collection`.
113
- /// @param collection ERC-721 collection contract address.
114
- /// @return Asset ID with `collection` embedded in bits [191:32].
115
- function toErc721(address collection) internal view returns (bytes32) {
116
- return bytes32(toLocalBase(Erc721) | (uint(uint160(collection)) << 32));
100
+ /// @notice Derive an opaque asset ID from a keccak preimage.
101
+ /// @param preimage Preimage whose first byte is `0x01`.
102
+ /// @return asset `0x00 || bytes31(keccak256(preimage))`.
103
+ function toKeccak(bytes memory preimage) internal pure returns (bytes32 asset) {
104
+ return Ids.toKeccak(preimage);
117
105
  }
118
106
 
119
- /// @notice Create a chain-local ERC-1155 asset ID for `collection`.
120
- /// @param collection ERC-1155 collection contract address.
121
- /// @return Asset ID with `collection` embedded in bits [191:32].
122
- function toErc1155(address collection) internal view returns (bytes32) {
123
- return bytes32(toLocalBase(Erc1155) | (uint(uint160(collection)) << 32));
107
+ /// @notice Assert that `asset` matches the opaque keccak ID for `preimage`.
108
+ /// @param asset Opaque asset ID to validate.
109
+ /// @param preimage Preimage whose first byte is `0x01`.
110
+ /// @return The same `asset` value if it matches.
111
+ function matchKeccak(bytes32 asset, bytes memory preimage) internal pure returns (bytes32) {
112
+ if (asset != Ids.toKeccak(preimage)) revert InvalidAsset();
113
+ return asset;
124
114
  }
125
115
 
126
116
  /// @notice Extract the ERC-20 contract address from an asset ID.
@@ -128,7 +118,7 @@ library Assets {
128
118
  /// @param asset ERC-20 asset identifier.
129
119
  /// @return Token contract address embedded in bits [191:32].
130
120
  function erc20Addr(bytes32 asset) internal view returns (address) {
131
- return address(uint160(uint(erc20(asset)) >> 32));
121
+ return ensureAddr(address(uint160(uint(erc20(asset)) >> 32)));
132
122
  }
133
123
 
134
124
  /// @notice Assert that `asset` is a local ERC-20 for `token` and return it unchanged.
@@ -141,56 +131,6 @@ library Assets {
141
131
  return asset;
142
132
  }
143
133
 
144
- /// @notice Extract the ERC-721 collection address from an asset ID.
145
- /// Reverts if `asset` is not a local ERC-721 asset.
146
- /// @param asset ERC-721 asset identifier.
147
- /// @return Collection contract address embedded in bits [191:32].
148
- function erc721Collection(bytes32 asset) internal view returns (address) {
149
- return address(uint160(uint(erc721(asset)) >> 32));
150
- }
151
-
152
- /// @notice Assert that `asset` is a local ERC-721 for `collection` and return it unchanged.
153
- /// Reverts if `asset` is not a local ERC-721 asset or if its collection address differs.
154
- /// @param asset ERC-721 asset identifier.
155
- /// @param collection Expected ERC-721 collection address.
156
- /// @return The same `asset` value if valid.
157
- function matchErc721(bytes32 asset, address collection) internal view returns (bytes32) {
158
- if (erc721Collection(asset) != collection) revert InvalidAsset();
159
- return asset;
160
- }
161
-
162
- /// @notice Extract the ERC-1155 collection address from an asset ID.
163
- /// Reverts if `asset` is not a local ERC-1155 asset.
164
- /// @param asset ERC-1155 asset identifier.
165
- /// @return Collection contract address embedded in bits [191:32].
166
- function erc1155Collection(bytes32 asset) internal view returns (address) {
167
- return address(uint160(uint(erc1155(asset)) >> 32));
168
- }
169
-
170
- /// @notice Assert that `asset` is a local ERC-1155 for `collection` and return it unchanged.
171
- /// Reverts if `asset` is not a local ERC-1155 asset or if its collection address differs.
172
- /// @param asset ERC-1155 asset identifier.
173
- /// @param collection Expected ERC-1155 collection address.
174
- /// @return The same `asset` value if valid.
175
- function matchErc1155(bytes32 asset, address collection) internal view returns (bytes32) {
176
- if (erc1155Collection(asset) != collection) revert InvalidAsset();
177
- return asset;
178
- }
179
-
180
- /// @notice Derive a storage slot for an (asset, meta) pair.
181
- /// For 32-byte assets (no meta), the slot is the asset ID itself.
182
- /// For assets with metadata (e.g. ERC-721 or ERC-1155 token IDs), the slot is
183
- /// `keccak256(asset ++ meta)`.
184
- /// Reverts only if `asset` is zero.
185
- /// For 32-byte assets, `meta` is ignored and does not affect the derived slot.
186
- /// @param asset Asset identifier.
187
- /// @param meta Asset metadata slot (e.g. token ID context).
188
- /// @return Storage slot for the (asset, meta) combination.
189
- function slot(bytes32 asset, bytes32 meta) internal pure returns (bytes32) {
190
- if (is32(asset)) return asset;
191
- if (meta == 0 || !is64(asset)) revert InvalidAsset();
192
- return keccak256(bytes.concat(asset, meta));
193
- }
194
134
  }
195
135
 
196
136
  /// @title Amounts