@rootzero/contracts 1.26.0 → 1.28.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 +48 -0
- package/Core.sol +2 -2
- package/Endpoints.sol +2 -2
- package/README.md +34 -20
- package/Utils.sol +1 -1
- package/codec/Blocks.sol +13 -13
- package/codec/Decoders.sol +1 -1
- package/codec/Keys.sol +1 -1
- package/codec/Schema.sol +8 -5
- package/codec/Specs.sol +3 -4
- package/codec/Writers.sol +2 -2
- package/commands/Bootstrap.sol +31 -45
- package/commands/Cashout.sol +3 -2
- package/commands/Credit.sol +3 -2
- package/commands/Debit.sol +3 -2
- package/commands/Recover.sol +2 -1
- package/commands/Relay.sol +3 -2
- package/commands/Repay.sol +3 -2
- package/commands/Settle.sol +3 -2
- package/commands/admin/Execute.sol +3 -1
- package/core/Access.sol +2 -3
- package/core/Calls.sol +83 -79
- package/core/Pipeline.sol +31 -27
- package/core/Portal.sol +2 -2
- package/core/Settlement.sol +2 -1
- package/core/Types.sol +1 -0
- package/execution/Budget.sol +8 -4
- package/execution/Execution.sol +8 -9
- package/package.json +1 -1
- package/ports/Dispatch.sol +3 -2
- package/utils/Accounts.sol +16 -7
- package/utils/Errors.sol +6 -0
- package/utils/Nodes.sol +15 -0
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,54 @@ sections are immutable and must continue to describe the tagged release.
|
|
|
8
8
|
|
|
9
9
|
## Unreleased
|
|
10
10
|
|
|
11
|
+
## 1.28.0
|
|
12
|
+
|
|
13
|
+
### Breaking Changes
|
|
14
|
+
|
|
15
|
+
- Expanded STEP's native `value` field from `uint128` to `uint`, increasing an
|
|
16
|
+
empty STEP block from 64 to 80 bytes. Plain native values now use `uint`
|
|
17
|
+
throughout runtime APIs; packed `resources` remain separate `uint` words
|
|
18
|
+
whose EVM value lane is extracted explicitly with `useResourceValue`.
|
|
19
|
+
- Replaced the `CommandCalls` abstraction and its allocating `encodeCommandCall`
|
|
20
|
+
and `callCommand` helpers with the free `rawCommandCall` function. The caller
|
|
21
|
+
now supplies the decoded selector and target after validating and authorizing
|
|
22
|
+
the command, then uses the single-scratch assembly call path.
|
|
23
|
+
- Added the required `ExecuteHook` to `Pipeline` and removed its `dispatch` hook.
|
|
24
|
+
Steps whose command IDs target the current host use `execute`; other commands
|
|
25
|
+
are checked through `TrustAccess` and called directly with `rawCommandCall`.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- Added the free `unpackCommand` utility for validating a command node and
|
|
30
|
+
extracting its selector and target in one operation. Pipeline steps now use
|
|
31
|
+
it to validate command IDs and select local execution by target address.
|
|
32
|
+
- Simplified `NodeAccess.ensureTrusted` to a single mapping check; an unset zero
|
|
33
|
+
node already resolves to false like every other untrusted node.
|
|
34
|
+
|
|
35
|
+
## 1.27.0
|
|
36
|
+
|
|
37
|
+
### Breaking Changes
|
|
38
|
+
|
|
39
|
+
- Removed `BootstrapBudgetHook`. Bootstrap budget contributions now debit the
|
|
40
|
+
account's local native asset through the standard `DebitAccountHook`.
|
|
41
|
+
- Removed the external `bootstrap` endpoint and `BootstrapInternal`. Bootstrap
|
|
42
|
+
is now a pipeline-local command implemented directly by `Bootstrap` while
|
|
43
|
+
retaining its registered command ID and descriptor metadata.
|
|
44
|
+
- Replaced the codec-specific `Executions.ZeroStride` error with global
|
|
45
|
+
`UnexpectedState` and `UnexpectedInput` errors for pipeline-local lane
|
|
46
|
+
violations.
|
|
47
|
+
|
|
48
|
+
### Changed
|
|
49
|
+
|
|
50
|
+
- Node authorization and revocation now reject foreign-chain and opaque node
|
|
51
|
+
IDs, keeping the trusted-node set local to the host chain.
|
|
52
|
+
- Asserting EVM, admin, and user account helpers now require a nonzero embedded
|
|
53
|
+
address while continuing to return the original account ID.
|
|
54
|
+
- Documented that either side of a position may be absent, using a zero
|
|
55
|
+
identifier and quantity like an omitted transaction endpoint.
|
|
56
|
+
- Bootstrap uses assigned step value before debiting any remaining native-asset
|
|
57
|
+
amount from the account and returns unused value as credit.
|
|
58
|
+
|
|
11
59
|
## 1.26.0
|
|
12
60
|
|
|
13
61
|
### Breaking Changes
|
package/Core.sol
CHANGED
|
@@ -12,9 +12,9 @@ import { Balances, InsufficientFunds } from "./core/Balances.sol";
|
|
|
12
12
|
import { Escrows, InsufficientEscrow } from "./core/Escrows.sol";
|
|
13
13
|
import { NativeAsset, Runtime } from "./core/Runtime.sol";
|
|
14
14
|
import { Admins, CommandHost, Guardians, Host, HostIntroduction, IHostIntroduction } from "./core/Host.sol";
|
|
15
|
-
import {
|
|
15
|
+
import { FailedCall, NodeCalls, PortCalls, RawNodeCalls, rawCommandCall } from "./core/Calls.sol";
|
|
16
16
|
import { EndpointBase, InputEndpointBase } from "./core/Endpoint.sol";
|
|
17
|
-
import { PipeHook, Pipeline } from "./core/Pipeline.sol";
|
|
17
|
+
import { ExecuteHook, PipeHook, Pipeline } from "./core/Pipeline.sol";
|
|
18
18
|
import { Budget, Budgets } from "./execution/Budget.sol";
|
|
19
19
|
import { CreditAccountHook, DebitAccountHook, PostHook, RepayHook, SettleHook, Settlement } from "./core/Settlement.sol";
|
|
20
20
|
import { Portal } from "./core/Portal.sol";
|
package/Endpoints.sol
CHANGED
|
@@ -6,14 +6,14 @@ pragma solidity ^0.8.33;
|
|
|
6
6
|
|
|
7
7
|
// Shared endpoint hooks
|
|
8
8
|
import {Flags} from "./codec/Descriptors.sol";
|
|
9
|
-
import {PipeHook} from "./core/Pipeline.sol";
|
|
9
|
+
import {ExecuteHook, PipeHook} from "./core/Pipeline.sol";
|
|
10
10
|
import {CreditAccountHook, DebitAccountHook, PostHook, RepayHook, SettleHook} from "./core/Settlement.sol";
|
|
11
11
|
|
|
12
12
|
// Commands
|
|
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
|
|
@@ -357,7 +365,7 @@ A single command is rarely the whole story. A pipeline is a run of `#step`
|
|
|
357
365
|
blocks executed in order within one transaction:
|
|
358
366
|
|
|
359
367
|
```txt
|
|
360
|
-
step { uint cmd,
|
|
368
|
+
step { uint cmd, uint value, #bytes as input }
|
|
361
369
|
```
|
|
362
370
|
|
|
363
371
|
Each step names a command, the native value it may spend, and its input.
|
|
@@ -367,23 +375,26 @@ 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 execution. This is the core of
|
|
372
383
|
`Pipeline.pipe`:
|
|
373
384
|
|
|
374
385
|
```solidity
|
|
375
386
|
while (cur.more()) {
|
|
376
|
-
(uint cmd,
|
|
387
|
+
(uint cmd, uint value, bytes calldata input) = cur.unpackStep();
|
|
388
|
+
(bytes4 selector, address target) = unpackCommand(cmd);
|
|
377
389
|
if (budget < value) revert InsufficientValue();
|
|
378
390
|
unchecked { budget -= value; }
|
|
379
391
|
uint credit;
|
|
380
|
-
(
|
|
381
|
-
cmd,
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
input
|
|
385
|
-
|
|
386
|
-
);
|
|
392
|
+
if (target == address(this)) {
|
|
393
|
+
(state, credit) = execute(cmd, account, state, input, value);
|
|
394
|
+
} else {
|
|
395
|
+
ensureTrusted(cmd);
|
|
396
|
+
(state, credit) = rawCommandCall(selector, target, value, account, state, input);
|
|
397
|
+
}
|
|
387
398
|
budget += credit;
|
|
388
399
|
}
|
|
389
400
|
if (state.length != 0) revert UnexpectedState();
|
|
@@ -396,21 +407,24 @@ settles that final value once.
|
|
|
396
407
|
A transfer, for instance, is a two-step pipeline: `debitAccount` turns an
|
|
397
408
|
`#amount` input into `#balance` state, and `payout` consumes that state
|
|
398
409
|
toward a recipient. Because a pipeline is just blocks, it is also the unit of
|
|
399
|
-
command batching. A step's `
|
|
400
|
-
native-value budget. Transport envelopes retain separate
|
|
401
|
-
`resources` fields for adapters that also need gas or runtime
|
|
410
|
+
command batching. A step's plain `uint value` is drawn directly from the shared
|
|
411
|
+
native-value budget. Transport envelopes retain separate opaque, packed
|
|
412
|
+
chain-specific `resources` fields for adapters that also need gas or runtime
|
|
413
|
+
parameters. A `resources` word is never itself native value; EVM adapters use
|
|
414
|
+
`useResourceValue` to extract its low 128-bit value lane before spending it.
|
|
402
415
|
|
|
403
|
-
Hosts that implement a pipeline locally can inherit `
|
|
416
|
+
Hosts that implement a pipeline locally can inherit `Bootstrap`,
|
|
404
417
|
`CashoutInternal`, `DebitAccountInternal`, `CreditAccountInternal`,
|
|
405
418
|
`SettleInternal`, and
|
|
406
|
-
`RepayInternal` to
|
|
419
|
+
`RepayInternal` to register canonical command metadata while routing
|
|
407
420
|
their local command IDs through `executeBootstrap`, `executeCashout`,
|
|
408
421
|
`executeDebitAccount`, `executeCreditAccount`, `executeSettle`, and
|
|
409
422
|
`executeRepay`. The bootstrap, cashout, and debit adapters decode fixed-stride
|
|
410
423
|
calldata input directly; the other three
|
|
411
424
|
decode memory-backed pipeline state. All avoid an external self-call. Pass the
|
|
412
|
-
step value into each adapter
|
|
413
|
-
|
|
425
|
+
step value into each adapter. Bootstrap is pipeline-local rather than an
|
|
426
|
+
externally callable command and may consume value for native-asset balance;
|
|
427
|
+
the other five reject nonzero value because those commands are non-funded.
|
|
414
428
|
|
|
415
429
|
Positions also support backward-composed pipelines. In an exact-output route,
|
|
416
430
|
the asset side can represent the desired result while the liability side
|
|
@@ -497,11 +511,11 @@ names, access sets, balances — from logs alone, with no artifact files.
|
|
|
497
511
|
Import from the package entry points rather than deep paths:
|
|
498
512
|
|
|
499
513
|
- `@rootzero/contracts/Core.sol` — `Host`, access control, `Balances`,
|
|
500
|
-
`Settlement`, `PipeHook`, `Pipeline`, `Portal`, validator
|
|
514
|
+
`Settlement`, `ExecuteHook`, `PipeHook`, `Pipeline`, `Portal`, validator
|
|
501
515
|
- `@rootzero/contracts/Commands.sol` — `CommandBase`, `Execution`, `Flags`,
|
|
502
516
|
codec helpers, and shared value types for authoring custom commands
|
|
503
517
|
- `@rootzero/contracts/Endpoints.sol` — command, admin, port, guard, and query
|
|
504
|
-
mixins, their hooks (including `PipeHook`), and `Flags`
|
|
518
|
+
mixins, their hooks (including `ExecuteHook` and `PipeHook`), and `Flags`
|
|
505
519
|
- `@rootzero/contracts/Codec.sol` — `Blocks`, calldata `Cur`/`Cursors`, memory
|
|
506
520
|
`Memory`, `Writers`, `Schemas`, `Descriptors`, `Flags`, `Keys`, and
|
|
507
521
|
`Specs`
|
package/Utils.sol
CHANGED
|
@@ -10,7 +10,7 @@ import { Actions } from "./utils/Actions.sol";
|
|
|
10
10
|
import { Amounts, Assets } from "./utils/Assets.sol";
|
|
11
11
|
import { ECDSA } from "./utils/ECDSA.sol";
|
|
12
12
|
import { Ids } from "./utils/Ids.sol";
|
|
13
|
-
import { Nodes } from "./utils/Nodes.sol";
|
|
13
|
+
import { Nodes, unpackCommand } from "./utils/Nodes.sol";
|
|
14
14
|
import { Layout } from "./utils/Layout.sol";
|
|
15
15
|
import { BadAmount, InsufficientValue, InvalidAccount, InvalidAsset, InvalidContract, InvalidId, InvalidPreimage, MissingCursor, NotDivisible, OutOfBounds, UnauthorizedAsset, UnconsumedData, UnexpectedPosition, ValueOverflow, ZeroAddress, ZeroAmount} from "./utils/Errors.sol";
|
|
16
16
|
import { addrOr, applyBps, beforeBps, bytes32ToInt, bytes32ToString, clear8, clear16, clear32, clear64, divisible, ensureAddr, ensureContract, hash32, intToBytes32, isFamily, matchesBase, MAX_BPS, max8, max16, max24, max32, max40, max64, max96, max128, max160, replace8, replace16, replace32, replace64, retryTicket, toLocalBase, toUnspecifiedBase } from "./utils/Utils.sol";
|
package/codec/Blocks.sol
CHANGED
|
@@ -761,17 +761,17 @@ library Blocks {
|
|
|
761
761
|
/// @param cmd Command identifier.
|
|
762
762
|
/// @param value Native value assigned to the step.
|
|
763
763
|
/// @param input Command input.
|
|
764
|
-
function writeStep(bytes memory dst, uint i, uint cmd,
|
|
765
|
-
uint len =
|
|
764
|
+
function writeStep(bytes memory dst, uint i, uint cmd, uint value, bytes memory input) internal pure {
|
|
765
|
+
uint len = 64 + Sizes.Header + input.length;
|
|
766
766
|
uint key = uint32(Keys.Step);
|
|
767
767
|
uint byteskey = uint32(Keys.Bytes);
|
|
768
768
|
assembly ("memory-safe") {
|
|
769
769
|
let p := add(add(dst, 0x20), i)
|
|
770
770
|
mstore(p, or(shl(224, key), shl(192, len)))
|
|
771
771
|
mstore(add(p, 0x08), cmd)
|
|
772
|
-
mstore(add(p, 0x28),
|
|
772
|
+
mstore(add(p, 0x28), value)
|
|
773
773
|
|
|
774
|
-
let q := add(p,
|
|
774
|
+
let q := add(p, 0x48)
|
|
775
775
|
let inputlen := mload(input)
|
|
776
776
|
mstore(q, or(shl(224, byteskey), shl(192, inputlen)))
|
|
777
777
|
mcopy(add(q, 0x08), add(input, 0x20), inputlen)
|
|
@@ -1031,17 +1031,17 @@ library Blocks {
|
|
|
1031
1031
|
}
|
|
1032
1032
|
|
|
1033
1033
|
/// @notice Encode a STEP block at `i`, copying its nested input from calldata.
|
|
1034
|
-
function copyStep(bytes memory dst, uint i, uint cmd,
|
|
1035
|
-
uint len = max32(
|
|
1034
|
+
function copyStep(bytes memory dst, uint i, uint cmd, uint value, bytes calldata input) internal pure {
|
|
1035
|
+
uint len = max32(64 + Sizes.Header + input.length);
|
|
1036
1036
|
uint key = uint32(Keys.Step);
|
|
1037
1037
|
uint byteskey = uint32(Keys.Bytes);
|
|
1038
1038
|
assembly ("memory-safe") {
|
|
1039
1039
|
let p := add(add(dst, 0x20), i)
|
|
1040
1040
|
mstore(p, or(shl(224, key), shl(192, len)))
|
|
1041
1041
|
mstore(add(p, 0x08), cmd)
|
|
1042
|
-
mstore(add(p, 0x28),
|
|
1042
|
+
mstore(add(p, 0x28), value)
|
|
1043
1043
|
|
|
1044
|
-
let q := add(p,
|
|
1044
|
+
let q := add(p, 0x48)
|
|
1045
1045
|
let inputlen := input.length
|
|
1046
1046
|
mstore(q, or(shl(224, byteskey), shl(192, inputlen)))
|
|
1047
1047
|
calldatacopy(add(q, 0x08), input.offset, inputlen)
|
|
@@ -1836,14 +1836,14 @@ library Blocks {
|
|
|
1836
1836
|
/// @return end Absolute position after the block.
|
|
1837
1837
|
function unpackStep(
|
|
1838
1838
|
uint abs
|
|
1839
|
-
) internal pure returns (uint cmd,
|
|
1839
|
+
) internal pure returns (uint cmd, uint value, bytes calldata input, uint end) {
|
|
1840
1840
|
uint limit;
|
|
1841
1841
|
(abs, limit) = expectKey(abs, Keys.Step);
|
|
1842
1842
|
assembly ("memory-safe") {
|
|
1843
1843
|
cmd := calldataload(abs)
|
|
1844
|
-
value :=
|
|
1844
|
+
value := calldataload(add(abs, 0x20))
|
|
1845
1845
|
}
|
|
1846
|
-
(input, end) = unpackBytes(abs +
|
|
1846
|
+
(input, end) = unpackBytes(abs + 64);
|
|
1847
1847
|
if (end != limit) revert InvalidBlock();
|
|
1848
1848
|
}
|
|
1849
1849
|
|
|
@@ -2203,14 +2203,14 @@ library Blocks {
|
|
|
2203
2203
|
/// @param value Native value assigned to the step.
|
|
2204
2204
|
/// @param input Raw nested input payload.
|
|
2205
2205
|
/// @return encoded Encoded STEP block bytes.
|
|
2206
|
-
function createStep(uint cmd,
|
|
2206
|
+
function createStep(uint cmd, uint value, bytes memory input) internal pure returns (bytes memory encoded) {
|
|
2207
2207
|
uint len = max32(Sizes.Step + input.length);
|
|
2208
2208
|
encoded = allocate(len);
|
|
2209
2209
|
writeStep(encoded, 0, cmd, value, input);
|
|
2210
2210
|
}
|
|
2211
2211
|
|
|
2212
2212
|
/// @notice Encode a STEP block by copying its nested input from calldata.
|
|
2213
|
-
function createStepCopy(uint cmd,
|
|
2213
|
+
function createStepCopy(uint cmd, uint value, bytes calldata input) internal pure returns (bytes memory encoded) {
|
|
2214
2214
|
uint len = max32(Sizes.Step + input.length);
|
|
2215
2215
|
encoded = allocate(len);
|
|
2216
2216
|
copyStep(encoded, 0, cmd, value, input);
|
package/codec/Decoders.sol
CHANGED
|
@@ -740,7 +740,7 @@ library Decoders {
|
|
|
740
740
|
/// @return input Decoded command input.
|
|
741
741
|
function unpackStep(
|
|
742
742
|
Cur memory cur
|
|
743
|
-
) internal pure returns (uint cmd,
|
|
743
|
+
) internal pure returns (uint cmd, uint value, bytes calldata input) {
|
|
744
744
|
uint abs = cur.state.absolute();
|
|
745
745
|
uint end;
|
|
746
746
|
(cmd, value, input, end) = Blocks.unpackStep(abs);
|
package/codec/Keys.sol
CHANGED
|
@@ -39,7 +39,7 @@ library Keys {
|
|
|
39
39
|
bytes4 constant Account = bytes4(keccak256("#account"));
|
|
40
40
|
/// @dev Transfer record passed through the pipeline - (bytes32 from, bytes32 to, bytes32 asset, uint amount)
|
|
41
41
|
bytes4 constant Transaction = bytes4(keccak256("#transaction"));
|
|
42
|
-
/// @dev Sub-command invocation - (uint cmd,
|
|
42
|
+
/// @dev Sub-command invocation - (uint cmd, uint value, #bytes as input)
|
|
43
43
|
bytes4 constant Step = bytes4(keccak256("#step"));
|
|
44
44
|
/// @dev Portal relay input - (uint portal, uint resources, #bytes as input)
|
|
45
45
|
bytes4 constant Relay = bytes4(keccak256("#relay"));
|
package/codec/Schema.sol
CHANGED
|
@@ -29,10 +29,11 @@ pragma solidity ^0.8.33;
|
|
|
29
29
|
// - `portal` fields identify destination portal hosts. By convention the value
|
|
30
30
|
// is the portal implementation's host ID; core passes it through unchanged
|
|
31
31
|
// and hooks may validate or resolve it for their transport
|
|
32
|
-
// - `resources` fields are chain-specific
|
|
33
|
-
// interprets them for the destination runtime. EVM
|
|
34
|
-
// 128 bits as native value
|
|
35
|
-
//
|
|
32
|
+
// - `resources` fields are opaque chain-specific packed words, not native
|
|
33
|
+
// values. A portal adapter interprets them for the destination runtime. EVM
|
|
34
|
+
// resources use the low 128 bits as native value, extracted explicitly with
|
|
35
|
+
// `useResourceValue` before spending.
|
|
36
|
+
// - STEP encodes native `value` directly as uint; it does not carry a
|
|
36
37
|
// chain-specific resources word
|
|
37
38
|
// - dotted field names and aliases, e.g. `dst.portal` or `#bytes as dst.payload`,
|
|
38
39
|
// are offchain projection metadata only and do not change runtime encoding
|
|
@@ -60,6 +61,8 @@ pragma solidity ^0.8.33;
|
|
|
60
61
|
// - while a balance, debt, or custody is in-flight as pipeline state, it is not simultaneously persisted
|
|
61
62
|
// in another ledger/store by this protocol
|
|
62
63
|
// - debt carries only a live liability side; position pairs live balance and debt sides
|
|
64
|
+
// - either position side may be absent by setting both its identifier and quantity to zero,
|
|
65
|
+
// analogous to omitting a transaction side with a zero `from` or `to`
|
|
63
66
|
// - debt and position state are transient and do not themselves create or erase an externally persisted obligation
|
|
64
67
|
// - positions support backward composition, but pipeline steps always execute in encoded order
|
|
65
68
|
// - commands must preserve, transform, settle, or intentionally consume pipeline state
|
|
@@ -114,7 +117,7 @@ library Schemas {
|
|
|
114
117
|
|
|
115
118
|
// Composite payloads
|
|
116
119
|
|
|
117
|
-
string constant Step = "uint cmd,
|
|
120
|
+
string constant Step = "uint cmd, uint value, #bytes as input";
|
|
118
121
|
string constant Call = "uint target, uint resources, #bytes as payload";
|
|
119
122
|
string constant Relay = "uint portal, uint resources, #bytes as input";
|
|
120
123
|
string constant Dispatch = "uint portal, uint resources, #bytes as payload";
|
package/codec/Specs.sol
CHANGED
|
@@ -21,8 +21,8 @@ library Sizes {
|
|
|
21
21
|
uint constant B128 = Header + 4 * Word;
|
|
22
22
|
/// @dev 8 header + 160 payload = 168 bytes total.
|
|
23
23
|
uint constant B160 = Header + 5 * Word;
|
|
24
|
-
/// @dev Minimum STEP size: 8 header + 32 command +
|
|
25
|
-
uint constant Step = 2 * Header +
|
|
24
|
+
/// @dev Minimum STEP size: 8 header + 32 command + 32 value + 8 nested BYTES header.
|
|
25
|
+
uint constant Step = 2 * Header + 2 * Word;
|
|
26
26
|
/// @dev STATUS block: 8 header + 32 status code = 40 bytes
|
|
27
27
|
uint constant Status = B32;
|
|
28
28
|
/// @dev CASHOUT block: 8 header + 32 native-asset amount = 40 bytes
|
|
@@ -64,7 +64,6 @@ library Specs {
|
|
|
64
64
|
uint private constant Exact128 = 128 * SizeFields;
|
|
65
65
|
uint private constant UnboundedHint128 = uint(128) << 136;
|
|
66
66
|
uint private constant UnboundedMin40Hint256 = (uint(40) << 192) | (uint(256) << 136);
|
|
67
|
-
uint private constant UnboundedMin56Hint256 = (uint(56) << 192) | (uint(256) << 136);
|
|
68
67
|
uint private constant UnboundedMin72Hint256 = (uint(72) << 192) | (uint(256) << 136);
|
|
69
68
|
uint private constant UnboundedMin48Hint512 = (uint(48) << 192) | (uint(512) << 136);
|
|
70
69
|
uint private constant UnboundedMin104Hint256 = (uint(104) << 192) | (uint(256) << 136);
|
|
@@ -85,7 +84,7 @@ library Specs {
|
|
|
85
84
|
uint constant String = uint(bytes32(Keys.String)) | UnboundedHint128;
|
|
86
85
|
uint constant Account = uint(bytes32(Keys.Account)) | Exact32;
|
|
87
86
|
uint constant Transaction = uint(bytes32(Keys.Transaction)) | Exact128;
|
|
88
|
-
uint constant Step = uint(bytes32(Keys.Step)) |
|
|
87
|
+
uint constant Step = uint(bytes32(Keys.Step)) | UnboundedMin72Hint256;
|
|
89
88
|
uint constant Relay = uint(bytes32(Keys.Relay)) | UnboundedMin72Hint256;
|
|
90
89
|
uint constant Context = uint(bytes32(Keys.Context)) | UnboundedMin48Hint512;
|
|
91
90
|
uint constant Recover = uint(bytes32(Keys.Recover)) | UnboundedMin104Hint256;
|
package/codec/Writers.sol
CHANGED
|
@@ -414,7 +414,7 @@ library Writers {
|
|
|
414
414
|
/// @param cmd Command identifier to encode.
|
|
415
415
|
/// @param value Native value to encode.
|
|
416
416
|
/// @param input Command input to encode.
|
|
417
|
-
function appendStep(Writer memory writer, uint cmd,
|
|
417
|
+
function appendStep(Writer memory writer, uint cmd, uint value, bytes memory input) internal pure {
|
|
418
418
|
uint size = Sizes.Step + input.length;
|
|
419
419
|
uint i = reserve(writer, size);
|
|
420
420
|
Blocks.writeStep(writer.dst, i, cmd, value, input);
|
|
@@ -561,7 +561,7 @@ library Writers {
|
|
|
561
561
|
}
|
|
562
562
|
|
|
563
563
|
/// @notice Append a STEP block by copying its nested input from calldata.
|
|
564
|
-
function copyStep(Writer memory writer, uint cmd,
|
|
564
|
+
function copyStep(Writer memory writer, uint cmd, uint value, bytes calldata input) internal pure {
|
|
565
565
|
uint size = Sizes.Step + input.length;
|
|
566
566
|
uint i = reserve(writer, size);
|
|
567
567
|
Blocks.copyStep(writer.dst, i, cmd, value, input);
|
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
|
+
uint 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
|
|
|
@@ -67,10 +68,10 @@ abstract contract CashoutInternal is Cashout {
|
|
|
67
68
|
bytes32 account,
|
|
68
69
|
bytes memory state,
|
|
69
70
|
bytes calldata input,
|
|
70
|
-
|
|
71
|
+
uint 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
|
|
|
@@ -58,10 +59,10 @@ abstract contract CreditAccountInternal is CreditAccount {
|
|
|
58
59
|
bytes32 account,
|
|
59
60
|
bytes memory state,
|
|
60
61
|
bytes calldata input,
|
|
61
|
-
|
|
62
|
+
uint 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
|
|
|
@@ -61,10 +62,10 @@ abstract contract DebitAccountInternal is DebitAccount {
|
|
|
61
62
|
bytes32 account,
|
|
62
63
|
bytes memory state,
|
|
63
64
|
bytes calldata input,
|
|
64
|
-
|
|
65
|
+
uint 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/Recover.sol
CHANGED
|
@@ -9,7 +9,8 @@ using Executions for Execution;
|
|
|
9
9
|
abstract contract RecoverPayableHook {
|
|
10
10
|
/// @notice Override to recover a witness through `handler`.
|
|
11
11
|
/// @param handler Port that should attempt recovery.
|
|
12
|
-
/// @param resources
|
|
12
|
+
/// @param resources Opaque packed chain-specific resources, not plain native
|
|
13
|
+
/// value. EVM handlers extract the low 128-bit value lane with `useResourceValue`.
|
|
13
14
|
/// @param key Recovery lookup key.
|
|
14
15
|
/// @param witness Witness payload used to prove and replay recovery.
|
|
15
16
|
/// @param funds Shared execution containing the source value budget.
|
package/commands/Relay.sol
CHANGED
|
@@ -13,8 +13,9 @@ abstract contract RelayPayableHook {
|
|
|
13
13
|
/// the source state is consumed before destination success is known.
|
|
14
14
|
/// @param portal Destination portal implementation's host ID. Implementations
|
|
15
15
|
/// may validate or resolve it for their transport.
|
|
16
|
-
/// @param resources
|
|
17
|
-
///
|
|
16
|
+
/// @param resources Opaque packed chain-specific destination resources, not
|
|
17
|
+
/// plain native value. EVM adapters extract the low 128-bit value lane with
|
|
18
|
+
/// `useResourceValue`; higher bits may encode execution gas or other data.
|
|
18
19
|
/// @param account Destination command account.
|
|
19
20
|
/// @param state Complete state forwarded into the destination context.
|
|
20
21
|
/// @param input Input forwarded into the destination context.
|
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
|
|
|
@@ -161,10 +162,10 @@ abstract contract RepayInternal is Repay {
|
|
|
161
162
|
bytes32 account,
|
|
162
163
|
bytes memory state,
|
|
163
164
|
bytes calldata input,
|
|
164
|
-
|
|
165
|
+
uint 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);
|