@rootzero/contracts 1.26.0 → 1.27.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.
- package/CHANGELOG.md +24 -0
- package/Endpoints.sol +1 -1
- package/README.md +18 -6
- package/codec/Schema.sol +2 -0
- package/commands/Bootstrap.sol +30 -44
- package/commands/Cashout.sol +2 -1
- package/commands/Credit.sol +2 -1
- package/commands/Debit.sol +2 -1
- package/commands/Repay.sol +2 -1
- package/commands/Settle.sol +2 -1
- package/core/Access.sol +1 -0
- package/core/Pipeline.sol +1 -4
- package/core/Settlement.sol +2 -1
- package/core/Types.sol +1 -0
- package/execution/Execution.sol +0 -3
- package/package.json +1 -1
- package/utils/Accounts.sol +16 -7
- package/utils/Errors.sol +6 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,30 @@ sections are immutable and must continue to describe the tagged release.
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 1.27.0
|
|
12
|
+
|
|
13
|
+
### Breaking Changes
|
|
14
|
+
|
|
15
|
+
- Removed `BootstrapBudgetHook`. Bootstrap budget contributions now debit the
|
|
16
|
+
account's local native asset through the standard `DebitAccountHook`.
|
|
17
|
+
- Removed the external `bootstrap` endpoint and `BootstrapInternal`. Bootstrap
|
|
18
|
+
is now a pipeline-local command implemented directly by `Bootstrap` while
|
|
19
|
+
retaining its registered command ID and descriptor metadata.
|
|
20
|
+
- Replaced the codec-specific `Executions.ZeroStride` error with global
|
|
21
|
+
`UnexpectedState` and `UnexpectedInput` errors for pipeline-local lane
|
|
22
|
+
violations.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Node authorization and revocation now reject foreign-chain and opaque node
|
|
27
|
+
IDs, keeping the trusted-node set local to the host chain.
|
|
28
|
+
- Asserting EVM, admin, and user account helpers now require a nonzero embedded
|
|
29
|
+
address while continuing to return the original account ID.
|
|
30
|
+
- Documented that either side of a position may be absent, using a zero
|
|
31
|
+
identifier and quantity like an omitted transaction endpoint.
|
|
32
|
+
- Bootstrap uses assigned step value before debiting any remaining native-asset
|
|
33
|
+
amount from the account and returns unused value as credit.
|
|
34
|
+
|
|
11
35
|
## 1.26.0
|
|
12
36
|
|
|
13
37
|
### Breaking Changes
|
package/Endpoints.sol
CHANGED
|
@@ -13,7 +13,7 @@ import {CreditAccountHook, DebitAccountHook, PostHook, RepayHook, SettleHook} fr
|
|
|
13
13
|
import {CommandBase} from "./commands/Base.sol";
|
|
14
14
|
import {Allocate, AllocateHook} from "./commands/Allocate.sol";
|
|
15
15
|
import {Burn, BurnHook} from "./commands/Burn.sol";
|
|
16
|
-
import {Bootstrap
|
|
16
|
+
import {Bootstrap} from "./commands/Bootstrap.sol";
|
|
17
17
|
import {Cashout, CashoutHook, CashoutInternal} from "./commands/Cashout.sol";
|
|
18
18
|
import {CreditAccount, CreditAccountInternal} from "./commands/Credit.sol";
|
|
19
19
|
import {DebitAccount, DebitAccountInternal} from "./commands/Debit.sol";
|
package/README.md
CHANGED
|
@@ -276,6 +276,14 @@ next. Balance carries `{ asset, amount }`, debt carries `{ liability, debt }`,
|
|
|
276
276
|
and position carries their flat combination
|
|
277
277
|
`{ asset, amount, liability, debt }`.
|
|
278
278
|
|
|
279
|
+
Either side of a position may be absent. An absent asset side is encoded as
|
|
280
|
+
`asset = 0, amount = 0`; an absent liability side is encoded as
|
|
281
|
+
`liability = 0, debt = 0`. This mirrors transaction blocks, where a zero `from`
|
|
282
|
+
or `to` omits that side of the transfer. A one-sided position remains useful
|
|
283
|
+
when a command must preserve position-shaped state for later composition;
|
|
284
|
+
otherwise the narrower `#balance` or `#debt` block expresses the same live
|
|
285
|
+
value more directly.
|
|
286
|
+
|
|
279
287
|
`#debt` and `#position` are general live state rather than persisted
|
|
280
288
|
lending-specific debt records. Debt carries value owed or required; position
|
|
281
289
|
pairs that liability with value acquired or controlled. A command may preserve
|
|
@@ -367,8 +375,11 @@ next step, allowing one command to fund later commands. The standard
|
|
|
367
375
|
`bootstrap` command consumes a stream of
|
|
368
376
|
`#bootstrap { bytes32 asset, uint amount, uint budget }` requests and atomically
|
|
369
377
|
debits each asset through the standard account hook, introduces matching
|
|
370
|
-
`#balance` state, and
|
|
371
|
-
hook.
|
|
378
|
+
`#balance` state, and debits each nonzero budget contribution from the account's
|
|
379
|
+
native asset through the same hook. Its pipeline-local implementation uses assigned step value first when
|
|
380
|
+
bootstrapping the native asset, debits any remainder from the account, and
|
|
381
|
+
returns unused assigned value as credit. Bootstrap is registered with command
|
|
382
|
+
metadata but is only executable through local pipeline dispatch. This is the core of
|
|
372
383
|
`Pipeline.pipe`:
|
|
373
384
|
|
|
374
385
|
```solidity
|
|
@@ -400,17 +411,18 @@ command batching. A step's `uint128 value` is drawn directly from the shared
|
|
|
400
411
|
native-value budget. Transport envelopes retain separate chain-specific
|
|
401
412
|
`resources` fields for adapters that also need gas or runtime parameters.
|
|
402
413
|
|
|
403
|
-
Hosts that implement a pipeline locally can inherit `
|
|
414
|
+
Hosts that implement a pipeline locally can inherit `Bootstrap`,
|
|
404
415
|
`CashoutInternal`, `DebitAccountInternal`, `CreditAccountInternal`,
|
|
405
416
|
`SettleInternal`, and
|
|
406
|
-
`RepayInternal` to
|
|
417
|
+
`RepayInternal` to register canonical command metadata while routing
|
|
407
418
|
their local command IDs through `executeBootstrap`, `executeCashout`,
|
|
408
419
|
`executeDebitAccount`, `executeCreditAccount`, `executeSettle`, and
|
|
409
420
|
`executeRepay`. The bootstrap, cashout, and debit adapters decode fixed-stride
|
|
410
421
|
calldata input directly; the other three
|
|
411
422
|
decode memory-backed pipeline state. All avoid an external self-call. Pass the
|
|
412
|
-
step value into each adapter
|
|
413
|
-
|
|
423
|
+
step value into each adapter. Bootstrap is pipeline-local rather than an
|
|
424
|
+
externally callable command and may consume value for native-asset balance;
|
|
425
|
+
the other five reject nonzero value because those commands are non-funded.
|
|
414
426
|
|
|
415
427
|
Positions also support backward-composed pipelines. In an exact-output route,
|
|
416
428
|
the asset side can represent the desired result while the liability side
|
package/codec/Schema.sol
CHANGED
|
@@ -60,6 +60,8 @@ pragma solidity ^0.8.33;
|
|
|
60
60
|
// - while a balance, debt, or custody is in-flight as pipeline state, it is not simultaneously persisted
|
|
61
61
|
// in another ledger/store by this protocol
|
|
62
62
|
// - debt carries only a live liability side; position pairs live balance and debt sides
|
|
63
|
+
// - either position side may be absent by setting both its identifier and quantity to zero,
|
|
64
|
+
// analogous to omitting a transaction side with a zero `from` or `to`
|
|
63
65
|
// - debt and position state are transient and do not themselves create or erase an externally persisted obligation
|
|
64
66
|
// - positions support backward composition, but pipeline steps always execute in encoded order
|
|
65
67
|
// - commands must preserve, transform, settle, or intentionally consume pipeline state
|
package/commands/Bootstrap.sol
CHANGED
|
@@ -1,33 +1,20 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {CommandBase, Specs} from "./Base.sol";
|
|
5
5
|
import {Blocks} from "../codec/Blocks.sol";
|
|
6
6
|
import {Sizes} from "../codec/Specs.sol";
|
|
7
7
|
import {Cursors} from "../utils/Cursors.sol";
|
|
8
8
|
import {DebitAccountHook} from "../core/Settlement.sol";
|
|
9
|
-
|
|
10
|
-
using Executions for Execution;
|
|
11
|
-
|
|
12
|
-
/// @notice Hook implemented by hosts that source bootstrap pipeline budget.
|
|
13
|
-
abstract contract BootstrapBudgetHook {
|
|
14
|
-
/// @notice Source native-value budget for `account` during bootstrap.
|
|
15
|
-
/// Called once per BOOTSTRAP input block.
|
|
16
|
-
/// @dev Implementations must revert unless the contribution can be made available.
|
|
17
|
-
/// A zero amount is valid and may return immediately without changing state.
|
|
18
|
-
/// @param account Account funding the pipeline.
|
|
19
|
-
/// @param amount Native value added to the pipeline budget.
|
|
20
|
-
function bootstrapBudget(bytes32 account, uint amount) internal virtual;
|
|
21
|
-
}
|
|
9
|
+
import {UnexpectedState} from "../utils/Errors.sol";
|
|
22
10
|
|
|
23
11
|
/// @title Bootstrap
|
|
24
|
-
/// @notice
|
|
25
|
-
abstract contract Bootstrap is CommandBase, DebitAccountHook
|
|
26
|
-
uint private immutable descriptor;
|
|
12
|
+
/// @notice Pipeline-local command that atomically starts with BALANCE state and native-value budget.
|
|
13
|
+
abstract contract Bootstrap is CommandBase, DebitAccountHook {
|
|
27
14
|
uint private immutable id;
|
|
28
15
|
|
|
29
16
|
constructor() {
|
|
30
|
-
(id,
|
|
17
|
+
(id,) = command("bootstrap", Specs.Empty, Specs.Bootstrap, Specs.Balance, 0);
|
|
31
18
|
}
|
|
32
19
|
|
|
33
20
|
/// @notice Return the registered BOOTSTRAP command ID.
|
|
@@ -35,57 +22,56 @@ abstract contract Bootstrap is CommandBase, DebitAccountHook, BootstrapBudgetHoo
|
|
|
35
22
|
return id;
|
|
36
23
|
}
|
|
37
24
|
|
|
38
|
-
/// @
|
|
39
|
-
///
|
|
40
|
-
/// @return output One BALANCE block per BOOTSTRAP input.
|
|
41
|
-
/// @return credit Sum of trusted native value contributed by every input.
|
|
25
|
+
/// @dev Bootstrap one local balance, using assigned value before debiting
|
|
26
|
+
/// any remaining native-asset amount from the account.
|
|
42
27
|
function bootstrap(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
28
|
+
bytes32 account,
|
|
29
|
+
bytes32 asset,
|
|
30
|
+
uint amount,
|
|
31
|
+
uint budget,
|
|
32
|
+
uint value
|
|
33
|
+
) private returns (uint) {
|
|
34
|
+
if (asset == nativeAsset) {
|
|
35
|
+
uint funded = amount < value ? amount : value;
|
|
36
|
+
unchecked {
|
|
37
|
+
amount -= funded;
|
|
38
|
+
value -= funded;
|
|
39
|
+
}
|
|
40
|
+
amount += budget;
|
|
41
|
+
} else {
|
|
42
|
+
if (amount != 0) debitAccount(account, asset, amount);
|
|
43
|
+
amount = budget;
|
|
53
44
|
}
|
|
54
45
|
|
|
55
|
-
|
|
46
|
+
if (amount != 0) debitAccount(account, nativeAsset, amount);
|
|
47
|
+
return value + budget;
|
|
56
48
|
}
|
|
57
|
-
}
|
|
58
49
|
|
|
59
|
-
/// @title BootstrapInternal
|
|
60
|
-
/// @notice Extends bootstrap with optimized local pipeline dispatch.
|
|
61
|
-
abstract contract BootstrapInternal is Bootstrap {
|
|
62
50
|
/// @notice Execute bootstrap directly against a calldata BOOTSTRAP stream.
|
|
63
51
|
/// @param account Account funding the pipeline.
|
|
64
52
|
/// @param state Empty pipeline state required by the command schema.
|
|
65
53
|
/// @param input BOOTSTRAP block stream.
|
|
66
|
-
/// @param value Native value
|
|
54
|
+
/// @param value Native value available to fund native-asset balances.
|
|
67
55
|
/// @return output One BALANCE block per BOOTSTRAP input.
|
|
68
|
-
/// @return credit
|
|
56
|
+
/// @return credit Sourced budget contributions plus unused assigned value.
|
|
69
57
|
function executeBootstrap(
|
|
70
58
|
bytes32 account,
|
|
71
59
|
bytes memory state,
|
|
72
60
|
bytes calldata input,
|
|
73
61
|
uint128 value
|
|
74
62
|
) internal returns (bytes memory output, uint credit) {
|
|
75
|
-
if (
|
|
76
|
-
if (state.length != 0) revert Executions.ZeroStride();
|
|
63
|
+
if (state.length != 0) revert UnexpectedState();
|
|
77
64
|
if (input.length % Sizes.Bootstrap != 0) revert Blocks.InvalidBlock();
|
|
78
65
|
|
|
79
66
|
(uint abs, uint end) = Cursors.bounds(input);
|
|
80
67
|
output = new bytes(input.length / Sizes.Bootstrap * Sizes.Balance);
|
|
68
|
+
credit = value;
|
|
81
69
|
uint i;
|
|
82
70
|
|
|
83
71
|
while (abs < end) {
|
|
84
72
|
(bytes32 asset, uint amount, uint budget) = Blocks.unpackBootstrap(abs);
|
|
85
|
-
|
|
86
|
-
bootstrapBudget(account, budget);
|
|
73
|
+
credit = bootstrap(account, asset, amount, budget, credit);
|
|
87
74
|
Blocks.writeBalance(output, i, asset, amount);
|
|
88
|
-
credit += budget;
|
|
89
75
|
unchecked {
|
|
90
76
|
abs += Sizes.Bootstrap;
|
|
91
77
|
i += Sizes.Balance;
|
package/commands/Cashout.sol
CHANGED
|
@@ -7,6 +7,7 @@ import {Sizes} from "../codec/Specs.sol";
|
|
|
7
7
|
import {Cursors} from "../utils/Cursors.sol";
|
|
8
8
|
import {Action} from "../annotations/Action.sol";
|
|
9
9
|
import {Actions} from "../utils/Actions.sol";
|
|
10
|
+
import {UnexpectedState} from "../utils/Errors.sol";
|
|
10
11
|
|
|
11
12
|
using Executions for Execution;
|
|
12
13
|
|
|
@@ -70,7 +71,7 @@ abstract contract CashoutInternal is Cashout {
|
|
|
70
71
|
uint128 value
|
|
71
72
|
) internal returns (bytes memory, uint) {
|
|
72
73
|
if (value != 0) revert ValueNotAllowed();
|
|
73
|
-
if (state.length != 0) revert
|
|
74
|
+
if (state.length != 0) revert UnexpectedState();
|
|
74
75
|
if (input.length % Sizes.Cashout != 0) revert Blocks.InvalidBlock();
|
|
75
76
|
|
|
76
77
|
(uint abs, uint end) = Cursors.bounds(input);
|
package/commands/Credit.sol
CHANGED
|
@@ -5,6 +5,7 @@ import {Execution, Executions, CommandBase, Specs} from "./Base.sol";
|
|
|
5
5
|
import {CreditAccountHook} from "../core/Settlement.sol";
|
|
6
6
|
import {Blocks, Memory} from "../codec/Blocks.sol";
|
|
7
7
|
import {Sizes} from "../codec/Specs.sol";
|
|
8
|
+
import {UnexpectedInput} from "../utils/Errors.sol";
|
|
8
9
|
|
|
9
10
|
using Executions for Execution;
|
|
10
11
|
|
|
@@ -61,7 +62,7 @@ abstract contract CreditAccountInternal is CreditAccount {
|
|
|
61
62
|
uint128 value
|
|
62
63
|
) internal returns (bytes memory, uint) {
|
|
63
64
|
if (value != 0) revert ValueNotAllowed();
|
|
64
|
-
if (input.length != 0) revert
|
|
65
|
+
if (input.length != 0) revert UnexpectedInput();
|
|
65
66
|
if (state.length == 0) revert Blocks.EmptyRun();
|
|
66
67
|
|
|
67
68
|
(uint abs, uint end) = Memory.bounds(state, Sizes.Balance);
|
package/commands/Debit.sol
CHANGED
|
@@ -6,6 +6,7 @@ import {DebitAccountHook} from "../core/Settlement.sol";
|
|
|
6
6
|
import {Blocks} from "../codec/Blocks.sol";
|
|
7
7
|
import {Sizes} from "../codec/Specs.sol";
|
|
8
8
|
import {Cursors} from "../utils/Cursors.sol";
|
|
9
|
+
import {UnexpectedState} from "../utils/Errors.sol";
|
|
9
10
|
|
|
10
11
|
using Executions for Execution;
|
|
11
12
|
|
|
@@ -64,7 +65,7 @@ abstract contract DebitAccountInternal is DebitAccount {
|
|
|
64
65
|
uint128 value
|
|
65
66
|
) internal returns (bytes memory, uint) {
|
|
66
67
|
if (value != 0) revert ValueNotAllowed();
|
|
67
|
-
if (state.length != 0) revert
|
|
68
|
+
if (state.length != 0) revert UnexpectedState();
|
|
68
69
|
if (input.length == 0) revert Blocks.EmptyRun();
|
|
69
70
|
if (input.length % Sizes.Amount != 0) revert Blocks.InvalidBlock();
|
|
70
71
|
|
package/commands/Repay.sol
CHANGED
|
@@ -7,6 +7,7 @@ import {Action} from "../annotations/Action.sol";
|
|
|
7
7
|
import {Actions} from "../utils/Actions.sol";
|
|
8
8
|
import {Blocks, Memory} from "../codec/Blocks.sol";
|
|
9
9
|
import {Sizes} from "../codec/Specs.sol";
|
|
10
|
+
import {UnexpectedInput} from "../utils/Errors.sol";
|
|
10
11
|
|
|
11
12
|
using Executions for Execution;
|
|
12
13
|
|
|
@@ -164,7 +165,7 @@ abstract contract RepayInternal is Repay {
|
|
|
164
165
|
uint128 value
|
|
165
166
|
) internal returns (bytes memory, uint) {
|
|
166
167
|
if (value != 0) revert ValueNotAllowed();
|
|
167
|
-
if (input.length != 0) revert
|
|
168
|
+
if (input.length != 0) revert UnexpectedInput();
|
|
168
169
|
if (state.length == 0) revert Blocks.EmptyRun();
|
|
169
170
|
|
|
170
171
|
(uint abs, uint end) = Memory.bounds(state, Sizes.Debt);
|
package/commands/Settle.sol
CHANGED
|
@@ -7,6 +7,7 @@ import {Action} from "../annotations/Action.sol";
|
|
|
7
7
|
import {Actions} from "../utils/Actions.sol";
|
|
8
8
|
import {Blocks, Memory} from "../codec/Blocks.sol";
|
|
9
9
|
import {Sizes} from "../codec/Specs.sol";
|
|
10
|
+
import {UnexpectedInput} from "../utils/Errors.sol";
|
|
10
11
|
|
|
11
12
|
using Executions for Execution;
|
|
12
13
|
|
|
@@ -111,7 +112,7 @@ abstract contract SettleInternal is Settle {
|
|
|
111
112
|
uint128 value
|
|
112
113
|
) internal returns (bytes memory, uint) {
|
|
113
114
|
if (value != 0) revert ValueNotAllowed();
|
|
114
|
-
if (input.length != 0) revert
|
|
115
|
+
if (input.length != 0) revert UnexpectedInput();
|
|
115
116
|
if (state.length == 0) revert Blocks.EmptyRun();
|
|
116
117
|
|
|
117
118
|
(uint abs, uint end) = Memory.bounds(state, Sizes.Position);
|
package/core/Access.sol
CHANGED
|
@@ -89,6 +89,7 @@ abstract contract NodeAccess is AdminAccess, TrustAccess, NodeEvent {
|
|
|
89
89
|
/// @param node Node ID to update.
|
|
90
90
|
/// @param active True to authorize the node, false to revoke it.
|
|
91
91
|
function setNode(uint node, bool active) internal {
|
|
92
|
+
node = Nodes.local(node);
|
|
92
93
|
nodes[node] = active;
|
|
93
94
|
emit Node(host, node, active);
|
|
94
95
|
}
|
package/core/Pipeline.sol
CHANGED
|
@@ -3,7 +3,7 @@ pragma solidity ^0.8.33;
|
|
|
3
3
|
|
|
4
4
|
import {Blocks} from "../codec/Blocks.sol";
|
|
5
5
|
import {Cursors} from "../utils/Cursors.sol";
|
|
6
|
-
import {InsufficientValue, OutOfBounds} from "../utils/Errors.sol";
|
|
6
|
+
import {InsufficientValue, OutOfBounds, UnexpectedState} from "../utils/Errors.sol";
|
|
7
7
|
|
|
8
8
|
/// @notice Hook implemented by hosts that execute encoded step streams.
|
|
9
9
|
abstract contract PipeHook {
|
|
@@ -19,9 +19,6 @@ abstract contract PipeHook {
|
|
|
19
19
|
/// @title Pipeline
|
|
20
20
|
/// @notice Core pipeline functionality shared by higher-level surfaces.
|
|
21
21
|
abstract contract Pipeline is PipeHook {
|
|
22
|
-
/// @dev Thrown when the pipeline finishes with non-empty threaded state.
|
|
23
|
-
error UnexpectedState();
|
|
24
|
-
|
|
25
22
|
/// @notice Override to dispatch one piped step.
|
|
26
23
|
/// Called once per STEP block. The returned state becomes the state passed to
|
|
27
24
|
/// the next step, and the final returned state must be empty. Returned
|
package/core/Settlement.sol
CHANGED
|
@@ -61,7 +61,8 @@ abstract contract Settlement is PostHook, SettleHook, RepayHook, DebitAccountHoo
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/// @notice Settle one position by crediting its asset and debiting its liability.
|
|
64
|
-
/// Skips either operation when its corresponding amount is zero
|
|
64
|
+
/// Skips either operation when its corresponding amount is zero, including
|
|
65
|
+
/// position sides encoded as absent with a zero identifier and quantity.
|
|
65
66
|
function settle(
|
|
66
67
|
bytes32 account,
|
|
67
68
|
bytes32 asset,
|
package/core/Types.sol
CHANGED
|
@@ -76,6 +76,7 @@ struct Debt {
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/// @notice Asset and liability pair threaded as live pipeline state.
|
|
79
|
+
/// Either side may be absent by setting both its identifier and quantity to zero.
|
|
79
80
|
struct Position {
|
|
80
81
|
/// @dev Identifier for the asset side.
|
|
81
82
|
bytes32 asset;
|
package/execution/Execution.sol
CHANGED
|
@@ -28,9 +28,6 @@ struct Execution {
|
|
|
28
28
|
library Executions {
|
|
29
29
|
using Cursors for uint;
|
|
30
30
|
|
|
31
|
-
/// @dev Command-defined lane policy rejected data in an expected-empty lane.
|
|
32
|
-
error ZeroStride();
|
|
33
|
-
|
|
34
31
|
// -------------------------------------------------------------------------
|
|
35
32
|
// Opening
|
|
36
33
|
// -------------------------------------------------------------------------
|
package/package.json
CHANGED
package/utils/Accounts.sol
CHANGED
|
@@ -34,6 +34,7 @@ library Accounts {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/// @notice Return true if `account` belongs to the EVM account family.
|
|
37
|
+
/// @dev Classification only; does not require a nonzero embedded address.
|
|
37
38
|
function isEvm(bytes32 account) internal pure returns (bool) {
|
|
38
39
|
return isFamily(uint(account), Family);
|
|
39
40
|
}
|
|
@@ -44,20 +45,24 @@ library Accounts {
|
|
|
44
45
|
}
|
|
45
46
|
|
|
46
47
|
/// @notice Return true if `account` is an admin account.
|
|
48
|
+
/// @dev Classification only; does not require a nonzero embedded address.
|
|
47
49
|
function isAdmin(bytes32 account) internal pure returns (bool) {
|
|
48
50
|
return prefix(account) == Admin;
|
|
49
51
|
}
|
|
50
52
|
|
|
51
53
|
/// @notice Return true if `account` is a user account.
|
|
54
|
+
/// @dev Classification only; does not require a nonzero embedded address.
|
|
52
55
|
function isUser(bytes32 account) internal pure returns (bool) {
|
|
53
56
|
return prefix(account) == User;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
/// @notice Assert that `value` belongs to the EVM account family
|
|
59
|
+
/// @notice Assert that `value` belongs to the EVM account family, contains
|
|
60
|
+
/// a nonzero embedded address, and return it unchanged.
|
|
57
61
|
/// @param value Account identifier to validate.
|
|
58
62
|
/// @return account The same `value` if it is an EVM account.
|
|
59
63
|
function evm(bytes32 value) internal pure returns (bytes32 account) {
|
|
60
|
-
if (!
|
|
64
|
+
if (!isFamily(uint(value), Family)) revert InvalidAccount();
|
|
65
|
+
ensureAddr(address(uint160(uint(value) >> 32)));
|
|
61
66
|
return value;
|
|
62
67
|
}
|
|
63
68
|
|
|
@@ -69,19 +74,23 @@ library Accounts {
|
|
|
69
74
|
return value;
|
|
70
75
|
}
|
|
71
76
|
|
|
72
|
-
/// @notice Assert that `value` is an admin account
|
|
77
|
+
/// @notice Assert that `value` is an admin account, contains a nonzero
|
|
78
|
+
/// embedded address, and return it unchanged.
|
|
73
79
|
/// @param value Account identifier to validate.
|
|
74
80
|
/// @return account The same `value` if it is an admin account.
|
|
75
81
|
function admin(bytes32 value) internal pure returns (bytes32 account) {
|
|
76
|
-
if (
|
|
82
|
+
if (uint32(uint(value) >> 224) != Admin) revert InvalidAccount();
|
|
83
|
+
ensureAddr(address(uint160(uint(value) >> 32)));
|
|
77
84
|
return value;
|
|
78
85
|
}
|
|
79
86
|
|
|
80
|
-
/// @notice Assert that `value` is a user account
|
|
87
|
+
/// @notice Assert that `value` is a user account, contains a nonzero
|
|
88
|
+
/// embedded address, and return it unchanged.
|
|
81
89
|
/// @param value Account identifier to validate.
|
|
82
90
|
/// @return account The same `value` if it is a user account.
|
|
83
91
|
function user(bytes32 value) internal pure returns (bytes32 account) {
|
|
84
|
-
if (
|
|
92
|
+
if (uint32(uint(value) >> 224) != User) revert InvalidAccount();
|
|
93
|
+
ensureAddr(address(uint160(uint(value) >> 32)));
|
|
85
94
|
return value;
|
|
86
95
|
}
|
|
87
96
|
|
|
@@ -120,6 +129,6 @@ library Accounts {
|
|
|
120
129
|
/// @param account EVM-family account ID.
|
|
121
130
|
/// @return Embedded address (bits [191:32] of the ID).
|
|
122
131
|
function addr(bytes32 account) internal pure returns (address) {
|
|
123
|
-
return
|
|
132
|
+
return address(uint160(uint(evm(account)) >> 32));
|
|
124
133
|
}
|
|
125
134
|
}
|
package/utils/Errors.sol
CHANGED
|
@@ -7,6 +7,12 @@ error InsufficientValue();
|
|
|
7
7
|
/// @dev Thrown when a decoder or execution is finalized with unread data.
|
|
8
8
|
error UnconsumedData();
|
|
9
9
|
|
|
10
|
+
/// @dev Thrown when an operation requires empty state but receives state data.
|
|
11
|
+
error UnexpectedState();
|
|
12
|
+
|
|
13
|
+
/// @dev Thrown when an operation requires empty input but receives input data.
|
|
14
|
+
error UnexpectedInput();
|
|
15
|
+
|
|
10
16
|
/// @dev Thrown when an ID does not match the expected convention or type.
|
|
11
17
|
error InvalidId();
|
|
12
18
|
|