@rootzero/contracts 1.22.0 → 1.23.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 (44) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/Endpoints.sol +2 -3
  3. package/Events.sol +1 -1
  4. package/README.md +13 -11
  5. package/annotations/Action.sol +1 -1
  6. package/annotations/Label.sol +1 -1
  7. package/annotations/Schema.sol +1 -1
  8. package/codec/Blocks.sol +39 -30
  9. package/commands/Allocate.sol +5 -8
  10. package/commands/Base.sol +29 -13
  11. package/commands/Burn.sol +5 -7
  12. package/commands/Credit.sol +5 -7
  13. package/commands/Debit.sol +5 -7
  14. package/commands/Deposit.sol +10 -14
  15. package/commands/Payout.sol +5 -8
  16. package/commands/Provision.sol +10 -14
  17. package/commands/Recover.sol +4 -6
  18. package/commands/Relay.sol +14 -21
  19. package/commands/Repay.sol +10 -14
  20. package/commands/Settle.sol +10 -14
  21. package/commands/Withdraw.sol +5 -7
  22. package/commands/admin/AllowAssets.sol +5 -7
  23. package/commands/admin/Allowance.sol +5 -7
  24. package/commands/admin/Annotate.sol +5 -7
  25. package/commands/admin/Appoint.sol +5 -7
  26. package/commands/admin/Authorize.sol +5 -7
  27. package/commands/admin/Base.sol +12 -3
  28. package/commands/admin/DenyAssets.sol +5 -7
  29. package/commands/admin/Dismiss.sol +5 -7
  30. package/commands/admin/Execute.sol +5 -7
  31. package/commands/admin/Unauthorize.sol +5 -7
  32. package/core/Calls.sol +72 -3
  33. package/core/Portal.sol +2 -2
  34. package/events/Positioned.sol +22 -0
  35. package/execution/Execution.sol +42 -0
  36. package/package.json +1 -1
  37. package/ports/Allowance.sol +22 -12
  38. package/ports/Assets.sol +99 -0
  39. package/utils/Cursors.sol +3 -3
  40. package/utils/Nodes.sol +1 -1
  41. package/utils/Utils.sol +31 -31
  42. package/events/Commander.sol +0 -19
  43. package/ports/AllowAssets.sol +0 -34
  44. package/ports/DenyAssets.sol +0 -34
@@ -22,21 +22,19 @@ abstract contract Unauthorize is AdminBase {
22
22
  }
23
23
 
24
24
  /// @notice Unauthorize each NODE block in the admin input.
25
- /// @param input NODE block stream.
25
+ /// @param context Admin command context carrying the NODE input stream.
26
26
  /// @return Empty output state.
27
27
  /// @return Empty transaction stream.
28
28
  function unauthorize(
29
- bytes32 account,
30
- bytes calldata state,
31
- bytes calldata input
32
- ) external onlyAdmin(account) returns (bytes memory, bytes memory) {
33
- Execution memory exec = openCommand(state, input, descriptor, 0);
29
+ bytes calldata context
30
+ ) external returns (bytes memory, bytes memory) {
31
+ Execution memory exec = openAdminCommand(context, descriptor, 0);
34
32
 
35
33
  while (exec.more()) {
36
34
  uint node = exec.unpackNode(Lanes.Input);
37
35
  setNode(node, false);
38
36
  }
39
37
 
40
- return close(exec, account);
38
+ return closeCommand(exec);
41
39
  }
42
40
  }
package/core/Calls.sol CHANGED
@@ -3,6 +3,9 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import {TrustAccess} from "./Access.sol";
5
5
  import {Nodes} from "../utils/Nodes.sol";
6
+ import {Keys} from "../codec/Keys.sol";
7
+ import {Sizes} from "../codec/Specs.sol";
8
+ import {max32} from "../utils/Utils.sol";
6
9
 
7
10
  /// @dev Emitted when a trusted inter-node call fails.
8
11
  /// @param addr Contract address that was called.
@@ -81,6 +84,50 @@ abstract contract NodeCalls is RawNodeCalls, TrustAccess {
81
84
  /// @title CommandCalls
82
85
  /// @notice Trusted command-call helpers for contracts that route command nodes.
83
86
  abstract contract CommandCalls is NodeCalls {
87
+ /// @dev Build `command(bytes)` calldata and its nested CONTEXT block in one allocation.
88
+ /// Threaded state is copied from memory and step input directly from calldata.
89
+ function encodeCommandCall(
90
+ bytes4 selector,
91
+ bytes32 account,
92
+ bytes memory state,
93
+ bytes calldata input
94
+ ) internal pure returns (bytes memory data) {
95
+ uint contextLen = max32(Sizes.B32 + 2 * Sizes.Header + state.length + input.length);
96
+ uint paddedContextLen = (contextLen + 31) & ~uint(31);
97
+ uint dataLen = 4 + 64 + paddedContextLen;
98
+
99
+ // Reserve one scratch word because the final eight-byte block header is
100
+ // written with mstore. Exclude that word from the returned calldata.
101
+ data = new bytes(dataLen + 32);
102
+
103
+ uint contextKey = uint32(Keys.Context);
104
+ uint bytesKey = uint32(Keys.Bytes);
105
+ assembly ("memory-safe") {
106
+ mstore(data, dataLen)
107
+ let out := add(data, 0x20)
108
+
109
+ // ABI envelope for command(bytes).
110
+ mstore(out, selector)
111
+ mstore(add(out, 0x04), 0x20)
112
+ mstore(add(out, 0x24), contextLen)
113
+
114
+ // CONTEXT(account, BYTES(state), BYTES(input)).
115
+ let context := add(out, 0x44)
116
+ mstore(context, or(shl(224, contextKey), shl(192, sub(contextLen, 8))))
117
+ mstore(add(context, 0x08), account)
118
+
119
+ let stateBlock := add(context, 0x28)
120
+ let stateLen := mload(state)
121
+ mstore(stateBlock, or(shl(224, bytesKey), shl(192, stateLen)))
122
+ mcopy(add(stateBlock, 0x08), add(state, 0x20), stateLen)
123
+
124
+ let inputBlock := add(add(stateBlock, 0x08), stateLen)
125
+ let inputLen := input.length
126
+ mstore(inputBlock, or(shl(224, bytesKey), shl(192, inputLen)))
127
+ calldatacopy(add(inputBlock, 0x08), input.offset, inputLen)
128
+ }
129
+ }
130
+
84
131
  /// @notice Encode and call a trusted command node.
85
132
  /// @param command Command node ID embedding the target selector.
86
133
  /// @param value Native value to forward in wei.
@@ -97,7 +144,7 @@ abstract contract CommandCalls is NodeCalls {
97
144
  bytes calldata input
98
145
  ) internal returns (bytes memory nextState, bytes memory transactions) {
99
146
  bytes4 selector = Nodes.commandSelector(command);
100
- bytes memory data = abi.encodeWithSelector(selector, account, state, input);
147
+ bytes memory data = encodeCommandCall(selector, account, state, input);
101
148
  return abi.decode(trustedCall(command, value, data), (bytes, bytes));
102
149
  }
103
150
  }
@@ -110,7 +157,18 @@ abstract contract PortCalls is NodeCalls {
110
157
  /// @param value Native value to forward in wei.
111
158
  /// @param input Port input block stream.
112
159
  /// @return success True if the low-level port call succeeded.
113
- function tryCallPort(uint port, uint128 value, bytes calldata input) internal returns (bool success) {
160
+ function tryCallPort(uint port, uint128 value, bytes memory input) internal returns (bool success) {
161
+ bytes4 selector = Nodes.portSelector(port);
162
+ bytes memory data = abi.encodeWithSelector(selector, input);
163
+ return tryTrustedCall(port, value, data);
164
+ }
165
+
166
+ /// @notice Try to encode and call a trusted port node by copying input from calldata.
167
+ /// @param port Port node ID embedding the target selector.
168
+ /// @param value Native value to forward in wei.
169
+ /// @param input Port input block stream.
170
+ /// @return success True if the low-level port call succeeded.
171
+ function tryCallPortCopy(uint port, uint128 value, bytes calldata input) internal returns (bool success) {
114
172
  bytes4 selector = Nodes.portSelector(port);
115
173
  bytes memory data = abi.encodeWithSelector(selector, input);
116
174
  return tryTrustedCall(port, value, data);
@@ -121,7 +179,18 @@ abstract contract PortCalls is NodeCalls {
121
179
  /// @param value Native value to forward in wei.
122
180
  /// @param input Port input block stream.
123
181
  /// @return Decoded port output block stream.
124
- function callPort(uint port, uint128 value, bytes calldata input) internal returns (bytes memory) {
182
+ function callPort(uint port, uint128 value, bytes memory input) internal returns (bytes memory) {
183
+ bytes4 selector = Nodes.portSelector(port);
184
+ bytes memory data = abi.encodeWithSelector(selector, input);
185
+ return abi.decode(trustedCall(port, value, data), (bytes));
186
+ }
187
+
188
+ /// @notice Encode and call a trusted port node by copying input from calldata.
189
+ /// @param port Port node ID embedding the target selector.
190
+ /// @param value Native value to forward in wei.
191
+ /// @param input Port input block stream.
192
+ /// @return Decoded port output block stream.
193
+ function callPortCopy(uint port, uint128 value, bytes calldata input) internal returns (bytes memory) {
125
194
  bytes4 selector = Nodes.portSelector(port);
126
195
  bytes memory data = abi.encodeWithSelector(selector, input);
127
196
  return abi.decode(trustedCall(port, value, data), (bytes));
package/core/Portal.sol CHANGED
@@ -21,7 +21,7 @@ abstract contract Portal is PortCalls, NodeAccess, UnresolvedEvent, ResolvedEven
21
21
  /// @param value Native EVM value assigned to the forwarding attempt.
22
22
  /// @return miss Message digest recorded for recovery when forwarding fails; zero on success.
23
23
  function forward(uint port, bytes32 key, bytes calldata message, uint128 value) internal returns (bytes32 miss) {
24
- if (tryCallPort(port, value, message)) return bytes32(0);
24
+ if (tryCallPortCopy(port, value, message)) return bytes32(0);
25
25
 
26
26
  miss = keccak256(message);
27
27
  unresolved[key] = miss;
@@ -37,6 +37,6 @@ abstract contract Portal is PortCalls, NodeAccess, UnresolvedEvent, ResolvedEven
37
37
  if (unresolved[key] != keccak256(witness)) revert BadWitness();
38
38
 
39
39
  delete unresolved[key];
40
- callPort(port, value, witness);
40
+ callPortCopy(port, value, witness);
41
41
  }
42
42
  }
@@ -0,0 +1,22 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {EventEmitter} from "./Emitter.sol";
5
+
6
+ /// @notice Emitted when an action produces an account position.
7
+ abstract contract PositionedEvent is EventEmitter {
8
+ string private constant ABI =
9
+ "event Positioned(bytes32 indexed account, bytes32 asset, uint amount, bytes32 liability, uint debt, uint32 action)";
10
+
11
+ /// @param account Account associated with the position.
12
+ /// @param asset Identifier for the asset side.
13
+ /// @param amount Quantity on the asset side.
14
+ /// @param liability Identifier for the liability side.
15
+ /// @param debt Quantity owed on the liability side.
16
+ /// @param action Primary operation hint from `Actions` that produced the position.
17
+ event Positioned(bytes32 indexed account, bytes32 asset, uint amount, bytes32 liability, uint debt, uint32 action);
18
+
19
+ constructor() {
20
+ emit EventAbi(ABI);
21
+ }
22
+ }
@@ -15,6 +15,7 @@ import {max16} from "../utils/Utils.sol";
15
15
  /// @dev `decoders` contains tagged input and state cursor lanes. Cursor operations
16
16
  /// select one logical lane by swapping it into the lower 128 bits.
17
17
  struct Execution {
18
+ bytes32 account;
18
19
  uint budget;
19
20
  uint decoders;
20
21
  uint writers;
@@ -195,6 +196,33 @@ library Executions {
195
196
  return exec.decoders.select(lane).absolute();
196
197
  }
197
198
 
199
+ /// @dev Return the complete validated calldata source for a decoder lane.
200
+ /// @dev Does not consume or depend on the lane's current position. A lane
201
+ /// absent because its descriptor is EMPTY returns an empty calldata slice.
202
+ /// @param exec Execution whose input or state source is requested.
203
+ /// @param lane Input or state decoder lane.
204
+ /// @return data Complete calldata region represented by the lane.
205
+ function raw(Execution memory exec, uint8 lane) private pure returns (bytes calldata data) {
206
+ if (!exec.decoders.contains(lane)) return msg.data[0:0];
207
+
208
+ uint cur = exec.decoders.select(lane);
209
+ (, uint offset, uint len) = cur.decode();
210
+ if (len > msg.data.length || offset > msg.data.length - len) revert Blocks.MalformedBlocks();
211
+ return msg.data[offset:offset + len];
212
+ }
213
+
214
+ /// @notice Return the complete validated command state without consuming it.
215
+ /// @dev Remains the complete original state after the state cursor advances.
216
+ function rawState(Execution memory exec) internal pure returns (bytes calldata) {
217
+ return raw(exec, Lanes.State);
218
+ }
219
+
220
+ /// @notice Return the complete validated endpoint input without consuming it.
221
+ /// @dev Remains the complete original input after the input cursor advances.
222
+ function rawInput(Execution memory exec) internal pure returns (bytes calldata) {
223
+ return raw(exec, Lanes.Input);
224
+ }
225
+
198
226
  /// @notice Return whether the next block on `lane` has `key` and an empty payload.
199
227
  /// @param exec Execution whose decoder is inspected without advancing.
200
228
  /// @param lane Decoder lane to inspect.
@@ -218,6 +246,20 @@ library Executions {
218
246
  exec.decoders = cur.seekAbs(end);
219
247
  }
220
248
 
249
+ /// @notice Validate and consume one block from a decoder lane, returning its complete encoding.
250
+ /// @param exec Execution whose selected decoder cursor is advanced past the block.
251
+ /// @param lane Execution decoder lane to select.
252
+ /// @param key Expected block key.
253
+ /// @return data Calldata view of the complete block, including its header.
254
+ function takeBlock(
255
+ Execution memory exec,
256
+ uint8 lane,
257
+ bytes4 key
258
+ ) internal pure returns (bytes calldata data) {
259
+ (uint abs, uint end) = consume(exec, lane, Specs.create(key, 0, 0, 0));
260
+ data = msg.data[abs - Sizes.Header:end];
261
+ }
262
+
221
263
  /// @notice Consume a matching empty block from an execution decoder lane when present.
222
264
  /// @param exec Execution whose selected decoder advances only for a matching empty block.
223
265
  /// @param lane Decoder lane to consume.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "1.22.0",
3
+ "version": "1.23.0",
4
4
  "description": "Solidity contracts and protocol building blocks for rootzero hosts and commands.",
5
5
  "private": false,
6
6
  "license": "GPL-3.0-only",
@@ -2,35 +2,45 @@
2
2
  pragma solidity ^0.8.33;
3
3
 
4
4
  import {PortBase} from "./Base.sol";
5
- import {AllowanceHook} from "../commands/admin/Allowance.sol";
6
5
  import {Specs} from "../Codec.sol";
7
6
  import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
7
 
9
8
  using Executions for Execution;
10
9
 
11
- /// @title AllowancePort
12
- /// @notice Port that lets a trusted peer host input or refresh its own allowance.
13
- /// Each AMOUNT block in the input is scoped to the peer host and passed to the
14
- /// shared allowance hook as a host-scoped allowance. Restricted to trusted peers.
15
- abstract contract AllowancePort is PortBase, AllowanceHook {
10
+ /// @notice Hook implemented by hosts that handle allowance requests from peers.
11
+ abstract contract RequestAllowanceHook {
12
+ /// @notice Override to handle one allowance request from a peer host.
13
+ /// @dev The implementation is responsible for validating the request and
14
+ /// deciding what allowance, if any, to grant.
15
+ /// @param peer Peer host node ID requesting the allowance.
16
+ /// @param asset Asset identifier supplied by the peer.
17
+ /// @param amount Allowance amount requested in the asset's native units.
18
+ function requestAllowance(uint peer, bytes32 asset, uint amount) internal virtual;
19
+ }
20
+
21
+ /// @title RequestAllowancePort
22
+ /// @notice Port that lets trusted peers request their own asset allowances.
23
+ /// Each AMOUNT block is scoped to the caller and passed unchanged to
24
+ /// `requestAllowance(peer, asset, amount)`.
25
+ abstract contract RequestAllowancePort is PortBase, RequestAllowanceHook {
16
26
  uint private immutable descriptor;
17
27
 
18
28
  constructor() {
19
- (, descriptor) = port("portAllowance", Specs.Amount, Specs.Empty, 0);
29
+ (, descriptor) = port("portRequestAllowance", Specs.Amount, Specs.Empty, 0);
20
30
  }
21
31
 
22
- /// @notice Execute the allowance port call.
23
- /// @param data AMOUNT block stream requested by the trusted peer.
32
+ /// @notice Request asset allowances for the calling peer.
33
+ /// @param data AMOUNT block stream supplied by the trusted peer.
24
34
  /// @return Empty response bytes.
25
- function portAllowance(bytes calldata data) external onlyPeer returns (bytes memory) {
35
+ function portRequestAllowance(bytes calldata data) external onlyPeer returns (bytes memory) {
26
36
  Execution memory exec = openInput(data, descriptor, 0);
27
37
  uint peer = caller();
28
38
 
29
39
  while (exec.more()) {
30
40
  (bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
31
- allowance(peer, asset, amount);
41
+ requestAllowance(peer, asset, amount);
32
42
  }
33
-
43
+
34
44
  return "";
35
45
  }
36
46
  }
@@ -0,0 +1,99 @@
1
+ // SPDX-License-Identifier: GPL-3.0-only
2
+ pragma solidity ^0.8.33;
3
+
4
+ import {PortBase} from "./Base.sol";
5
+ import {AllowAssetsHook} from "../commands/admin/AllowAssets.sol";
6
+ import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
7
+ import {Specs} from "../Codec.sol";
8
+ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
9
+
10
+ using Executions for Execution;
11
+
12
+ /// @title AllowAssetsPort
13
+ /// @notice Port that permits a list of assets on behalf of a peer host.
14
+ /// Each ASSET block in the input calls `allowAsset`. Restricted to trusted peers.
15
+ abstract contract AllowAssetsPort is PortBase, AllowAssetsHook {
16
+ uint private immutable descriptor;
17
+
18
+ constructor() {
19
+ (, descriptor) = port("portAllowAssets", Specs.Asset, Specs.Empty, 0);
20
+ }
21
+
22
+ /// @notice Execute the allow-assets peer call.
23
+ /// @param data ASSET block stream supplied by the trusted peer.
24
+ /// @return Empty response bytes.
25
+ function portAllowAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
26
+ Execution memory exec = openInput(data, descriptor, 0);
27
+
28
+ while (exec.more()) {
29
+ bytes32 asset = exec.unpackAsset(Lanes.Input);
30
+ allowAsset(asset);
31
+ }
32
+
33
+ return "";
34
+ }
35
+ }
36
+
37
+ /// @title DenyAssetsPort
38
+ /// @notice Port that blocks a list of assets on behalf of a peer host.
39
+ /// Each ASSET block in the input calls `denyAsset`. Restricted to trusted peers.
40
+ abstract contract DenyAssetsPort is PortBase, DenyAssetsHook {
41
+ uint private immutable descriptor;
42
+
43
+ constructor() {
44
+ (, descriptor) = port("portDenyAssets", Specs.Asset, Specs.Empty, 0);
45
+ }
46
+
47
+ /// @notice Execute the deny-assets peer call.
48
+ /// @param data ASSET block stream supplied by the trusted peer.
49
+ /// @return Empty response bytes.
50
+ function portDenyAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
51
+ Execution memory exec = openInput(data, descriptor, 0);
52
+
53
+ while (exec.more()) {
54
+ bytes32 asset = exec.unpackAsset(Lanes.Input);
55
+ denyAsset(asset);
56
+ }
57
+
58
+ return "";
59
+ }
60
+ }
61
+
62
+ /// @notice Hook implemented by hosts that fulfill asset requests from peers.
63
+ abstract contract RequestAssetHook {
64
+ /// @notice Override to handle one asset request from a peer host.
65
+ /// @dev The implementation is responsible for validating `asset`, enforcing
66
+ /// requester policy, and sending the approved amount to the requester.
67
+ /// @param peer Peer host node ID for this request.
68
+ /// @param asset Asset identifier supplied by the peer.
69
+ /// @param amount Amount requested in the asset's native units.
70
+ function requestAsset(uint peer, bytes32 asset, uint amount) internal virtual;
71
+ }
72
+
73
+ /// @title RequestAssetPort
74
+ /// @notice Port that lets trusted peers request assets from the receiving host.
75
+ /// Each AMOUNT block is scoped to the caller and passed unchanged to
76
+ /// `requestAsset(peer, asset, amount)`. The hook validates support and performs
77
+ /// any accounting and transfer required by the host.
78
+ abstract contract RequestAssetPort is PortBase, RequestAssetHook {
79
+ uint private immutable descriptor;
80
+
81
+ constructor() {
82
+ (, descriptor) = port("portRequestAsset", Specs.Amount, Specs.Empty, 0);
83
+ }
84
+
85
+ /// @notice Request assets for the calling peer.
86
+ /// @param data AMOUNT block stream supplied by the trusted peer.
87
+ /// @return Empty response bytes.
88
+ function portRequestAsset(bytes calldata data) external onlyPeer returns (bytes memory) {
89
+ Execution memory exec = openInput(data, descriptor, 0);
90
+ uint peer = caller();
91
+
92
+ while (exec.more()) {
93
+ (bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
94
+ requestAsset(peer, asset, amount);
95
+ }
96
+
97
+ return "";
98
+ }
99
+ }
package/utils/Cursors.sol CHANGED
@@ -65,9 +65,9 @@ library Cursors {
65
65
  /// @param tag Cursor identity tag.
66
66
  /// @return cur Packed cursor.
67
67
  function create(uint offset, uint len, uint items, uint8 flags, uint8 tag) internal pure returns (uint cur) {
68
- cur |= max32(offset) << 32;
69
- cur |= max32(len) << 64;
70
- cur |= max16(items) << 96;
68
+ cur |= uint(max32(offset)) << 32;
69
+ cur |= uint(max32(len)) << 64;
70
+ cur |= uint(max16(items)) << 96;
71
71
  cur |= uint(flags) << 112;
72
72
  cur |= uint(tag) << 120;
73
73
  }
package/utils/Nodes.sol CHANGED
@@ -198,7 +198,7 @@ library Nodes {
198
198
  /// @return node Command node ID embedding both the selector and address.
199
199
  function toCommand(string memory name, address target) internal view returns (uint node) {
200
200
  node = toLocalBase(Command) | uint(uint160(target));
201
- node |= uint(uint32(toSelector(name, "(bytes32,bytes,bytes)"))) << 160;
201
+ node |= uint(uint32(toSelector(name, "(bytes)"))) << 160;
202
202
  }
203
203
 
204
204
  /// @notice Build a chain-local port ID for the given endpoint name and contract.
package/utils/Utils.sol CHANGED
@@ -11,76 +11,76 @@ error NotDivisible();
11
11
  /// @dev Thrown when an ID claims to carry an address but the embedded address is zero.
12
12
  error ZeroAddress();
13
13
 
14
- /// @notice Assert that `value` fits in uint8 and return it unchanged.
15
- function max8(uint value) pure returns (uint) {
14
+ /// @notice Assert that `value` fits in uint8 and return it as uint8.
15
+ function max8(uint value) pure returns (uint8) {
16
16
  if (value > type(uint8).max) {
17
17
  revert ValueOverflow();
18
18
  }
19
- return value;
19
+ return uint8(value);
20
20
  }
21
21
 
22
- /// @notice Assert that `value` fits in uint16 and return it unchanged.
23
- function max16(uint value) pure returns (uint) {
22
+ /// @notice Assert that `value` fits in uint16 and return it as uint16.
23
+ function max16(uint value) pure returns (uint16) {
24
24
  if (value > type(uint16).max) {
25
25
  revert ValueOverflow();
26
26
  }
27
- return value;
27
+ return uint16(value);
28
28
  }
29
29
 
30
- /// @notice Assert that `value` fits in uint24 and return it unchanged.
31
- function max24(uint value) pure returns (uint) {
30
+ /// @notice Assert that `value` fits in uint24 and return it as uint24.
31
+ function max24(uint value) pure returns (uint24) {
32
32
  if (value > type(uint24).max) {
33
33
  revert ValueOverflow();
34
34
  }
35
- return value;
35
+ return uint24(value);
36
36
  }
37
37
 
38
- /// @notice Assert that `value` fits in uint32 and return it unchanged.
39
- function max32(uint value) pure returns (uint) {
38
+ /// @notice Assert that `value` fits in uint32 and return it as uint32.
39
+ function max32(uint value) pure returns (uint32) {
40
40
  if (value > type(uint32).max) {
41
41
  revert ValueOverflow();
42
42
  }
43
- return value;
43
+ return uint32(value);
44
44
  }
45
45
 
46
- /// @notice Assert that `value` fits in uint40 and return it unchanged.
47
- function max40(uint value) pure returns (uint) {
46
+ /// @notice Assert that `value` fits in uint40 and return it as uint40.
47
+ function max40(uint value) pure returns (uint40) {
48
48
  if (value > type(uint40).max) {
49
49
  revert ValueOverflow();
50
50
  }
51
- return value;
51
+ return uint40(value);
52
52
  }
53
53
 
54
- /// @notice Assert that `value` fits in uint64 and return it unchanged.
55
- function max64(uint value) pure returns (uint) {
54
+ /// @notice Assert that `value` fits in uint64 and return it as uint64.
55
+ function max64(uint value) pure returns (uint64) {
56
56
  if (value > type(uint64).max) {
57
57
  revert ValueOverflow();
58
58
  }
59
- return value;
59
+ return uint64(value);
60
60
  }
61
61
 
62
- /// @notice Assert that `value` fits in uint96 and return it unchanged.
63
- function max96(uint value) pure returns (uint) {
62
+ /// @notice Assert that `value` fits in uint96 and return it as uint96.
63
+ function max96(uint value) pure returns (uint96) {
64
64
  if (value > type(uint96).max) {
65
65
  revert ValueOverflow();
66
66
  }
67
- return value;
67
+ return uint96(value);
68
68
  }
69
69
 
70
- /// @notice Assert that `value` fits in uint128 and return it unchanged.
71
- function max128(uint value) pure returns (uint) {
70
+ /// @notice Assert that `value` fits in uint128 and return it as uint128.
71
+ function max128(uint value) pure returns (uint128) {
72
72
  if (value > type(uint128).max) {
73
73
  revert ValueOverflow();
74
74
  }
75
- return value;
75
+ return uint128(value);
76
76
  }
77
77
 
78
- /// @notice Assert that `value` fits in uint160 and return it unchanged.
79
- function max160(uint value) pure returns (uint) {
78
+ /// @notice Assert that `value` fits in uint160 and return it as uint160.
79
+ function max160(uint value) pure returns (uint160) {
80
80
  if (value > type(uint160).max) {
81
81
  revert ValueOverflow();
82
82
  }
83
- return value;
83
+ return uint160(value);
84
84
  }
85
85
 
86
86
  // Packed fields
@@ -108,25 +108,25 @@ function clear64(uint value, uint shift) pure returns (uint) {
108
108
  /// @notice Replace the 8-bit field beginning at `shift` with `field`.
109
109
  /// @dev Reverts when `field` does not fit in 8 bits.
110
110
  function replace8(uint value, uint shift, uint field) pure returns (uint) {
111
- return clear8(value, shift) | (max8(field) << shift);
111
+ return clear8(value, shift) | (uint(max8(field)) << shift);
112
112
  }
113
113
 
114
114
  /// @notice Replace the 16-bit field beginning at `shift` with `field`.
115
115
  /// @dev Reverts when `field` does not fit in 16 bits.
116
116
  function replace16(uint value, uint shift, uint field) pure returns (uint) {
117
- return clear16(value, shift) | (max16(field) << shift);
117
+ return clear16(value, shift) | (uint(max16(field)) << shift);
118
118
  }
119
119
 
120
120
  /// @notice Replace the 32-bit field beginning at `shift` with `field`.
121
121
  /// @dev Reverts when `field` does not fit in 32 bits.
122
122
  function replace32(uint value, uint shift, uint field) pure returns (uint) {
123
- return clear32(value, shift) | (max32(field) << shift);
123
+ return clear32(value, shift) | (uint(max32(field)) << shift);
124
124
  }
125
125
 
126
126
  /// @notice Replace the 64-bit field beginning at `shift` with `field`.
127
127
  /// @dev Reverts when `field` does not fit in 64 bits.
128
128
  function replace64(uint value, uint shift, uint field) pure returns (uint) {
129
- return clear64(value, shift) | (max64(field) << shift);
129
+ return clear64(value, shift) | (uint(max64(field)) << shift);
130
130
  }
131
131
 
132
132
  /// @notice Assert that `n` is evenly divisible by `divisor`.
@@ -1,19 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import {EventEmitter} from "./Emitter.sol";
5
-
6
- /// @notice Emitted when a commander is announced for a chain/domain.
7
- abstract contract CommanderEvent is EventEmitter {
8
- string private constant ABI = "event Commander(uint indexed host, uint chain, bytes32 native, bytes32 admin)";
9
-
10
- /// @param host Commander host node ID for the chain.
11
- /// @param chain Chain/domain node ID.
12
- /// @param native Native asset ID for the chain.
13
- /// @param admin Admin account for the commander host on the chain.
14
- event Commander(uint indexed host, uint chain, bytes32 native, bytes32 admin);
15
-
16
- constructor() {
17
- emit EventAbi(ABI);
18
- }
19
- }
@@ -1,34 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import {PortBase} from "./Base.sol";
5
- import {AllowAssetsHook} from "../commands/admin/AllowAssets.sol";
6
- import {Specs} from "../Codec.sol";
7
- import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
-
9
- using Executions for Execution;
10
-
11
- /// @title AllowAssetsPort
12
- /// @notice Port that permits a list of assets on behalf of a peer host.
13
- /// Each ASSET block in the input calls `allowAsset`. Restricted to trusted peers.
14
- abstract contract AllowAssetsPort is PortBase, AllowAssetsHook {
15
- uint private immutable descriptor;
16
-
17
- constructor() {
18
- (, descriptor) = port("portAllowAssets", Specs.Asset, Specs.Empty, 0);
19
- }
20
-
21
- /// @notice Execute the allow-assets peer call.
22
- /// @param data ASSET block stream supplied by the trusted peer.
23
- /// @return Empty response bytes.
24
- function portAllowAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
25
- Execution memory exec = openInput(data, descriptor, 0);
26
-
27
- while (exec.more()) {
28
- bytes32 asset = exec.unpackAsset(Lanes.Input);
29
- allowAsset(asset);
30
- }
31
-
32
- return "";
33
- }
34
- }
@@ -1,34 +0,0 @@
1
- // SPDX-License-Identifier: GPL-3.0-only
2
- pragma solidity ^0.8.33;
3
-
4
- import {PortBase} from "./Base.sol";
5
- import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
6
- import {Specs} from "../Codec.sol";
7
- import {Execution, Executions, Lanes} from "../execution/Execution.sol";
8
-
9
- using Executions for Execution;
10
-
11
- /// @title DenyAssetsPort
12
- /// @notice Port that blocks a list of assets on behalf of a peer host.
13
- /// Each ASSET block in the input calls `denyAsset`. Restricted to trusted peers.
14
- abstract contract DenyAssetsPort is PortBase, DenyAssetsHook {
15
- uint private immutable descriptor;
16
-
17
- constructor() {
18
- (, descriptor) = port("portDenyAssets", Specs.Asset, Specs.Empty, 0);
19
- }
20
-
21
- /// @notice Execute the deny-assets peer call.
22
- /// @param data ASSET block stream supplied by the trusted peer.
23
- /// @return Empty response bytes.
24
- function portDenyAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
25
- Execution memory exec = openInput(data, descriptor, 0);
26
-
27
- while (exec.more()) {
28
- bytes32 asset = exec.unpackAsset(Lanes.Input);
29
- denyAsset(asset);
30
- }
31
-
32
- return "";
33
- }
34
- }