@rootzero/contracts 1.23.0 → 1.24.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 +39 -0
- package/Codec.sol +1 -1
- package/Commands.sol +1 -1
- package/Core.sol +2 -2
- package/Endpoints.sol +8 -1
- package/README.md +27 -21
- package/Utils.sol +1 -1
- package/annotations/Schema.sol +1 -7
- package/codec/Blocks.sol +74 -3
- package/codec/Decoders.sol +18 -1
- package/codec/Descriptors.sol +3 -1
- package/codec/Keys.sol +2 -0
- package/codec/Readers.sol +12 -0
- package/codec/Schema.sol +5 -4
- package/codec/Specs.sol +3 -0
- package/codec/Writers.sol +12 -1
- package/commands/Repay.sol +110 -10
- package/core/Access.sol +8 -0
- package/core/Types.sol +8 -0
- package/execution/Execution.sol +24 -1
- package/package.json +1 -1
- package/utils/Utils.sol +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,45 @@
|
|
|
3
3
|
Until the protocol reaches integration-stable status, minor versions may include
|
|
4
4
|
breaking API changes. Breaking changes are called out explicitly.
|
|
5
5
|
|
|
6
|
+
Add all changes made after a release to `Unreleased`. Published version
|
|
7
|
+
sections are immutable and must continue to describe the tagged release.
|
|
8
|
+
|
|
9
|
+
## Unreleased
|
|
10
|
+
|
|
11
|
+
## 1.24.0
|
|
12
|
+
|
|
13
|
+
### Breaking Changes
|
|
14
|
+
|
|
15
|
+
- Renamed the existing `Position`-consuming `repay` and `repayPayable`
|
|
16
|
+
commands to `repayPosition` and `repayPositionPayable`. Their state
|
|
17
|
+
transition remains `Position` to `Balance`; the new commands using the old
|
|
18
|
+
names consume `Debt` and return empty state. Command selectors and node IDs
|
|
19
|
+
for position repayment therefore change.
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- Added the standalone `Debt { liability, debt }` pipeline state, its standard
|
|
24
|
+
block key and schema, and codec support across blocks, readers, writers,
|
|
25
|
+
decoders, and execution helpers.
|
|
26
|
+
- Added `repay` and `repayPayable` commands that consume `Debt` state and return
|
|
27
|
+
empty state.
|
|
28
|
+
- Added `RepayInternal` for dispatching the non-funded `repay` command directly
|
|
29
|
+
against memory-backed pipeline state.
|
|
30
|
+
- Added unchecked `Blocks.read1`, `read2`, `read8`, and `read16` absolute
|
|
31
|
+
calldata helpers, completing the power-of-two family alongside `read4` and
|
|
32
|
+
`read32`.
|
|
33
|
+
- Added the standalone `ensureContract` utility and shared `InvalidContract`
|
|
34
|
+
error for uniformly requiring addresses with deployed bytecode.
|
|
35
|
+
- Added the free `enforceSender` access helper for requiring an exact
|
|
36
|
+
`msg.sender` with the shared `AccessDenied` error.
|
|
37
|
+
- Documented descriptor flag bits 6 and 7 as endpoint-defined custom flags;
|
|
38
|
+
bits 2 through 5 remain reserved for future protocol flags.
|
|
39
|
+
|
|
40
|
+
### Changed
|
|
41
|
+
|
|
42
|
+
- Repayment commands now publish the canonical `Actions.Repay` annotation
|
|
43
|
+
instead of `Actions.Settle`.
|
|
44
|
+
|
|
6
45
|
## 1.23.0
|
|
7
46
|
|
|
8
47
|
### Breaking Changes
|
package/Codec.sol
CHANGED
|
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
// Aggregator: re-exports the complete block encoding and decoding surface.
|
|
5
5
|
// Import this file for low-level codec extensions and direct stream processing.
|
|
6
6
|
|
|
7
|
-
import { AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Position, Tx } from "./core/Types.sol";
|
|
7
|
+
import { AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Debt, Position, Tx } from "./core/Types.sol";
|
|
8
8
|
import { Keys } from "./codec/Keys.sol";
|
|
9
9
|
import { Sizes, Specs } from "./codec/Specs.sol";
|
|
10
10
|
import { Descriptors, Flags } from "./codec/Descriptors.sol";
|
package/Commands.sol
CHANGED
|
@@ -12,4 +12,4 @@ import {Blocks} from "./codec/Blocks.sol";
|
|
|
12
12
|
import {Sizes, Specs} from "./codec/Specs.sol";
|
|
13
13
|
import {Decoders} from "./codec/Decoders.sol";
|
|
14
14
|
import {Cursors, Cur} from "./utils/Cursors.sol";
|
|
15
|
-
import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Position, Tx} from "./core/Types.sol";
|
|
15
|
+
import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Debt, Position, Tx} from "./core/Types.sol";
|
package/Core.sol
CHANGED
|
@@ -7,7 +7,7 @@ pragma solidity ^0.8.33;
|
|
|
7
7
|
import { Action } from "./annotations/Action.sol";
|
|
8
8
|
import { Label } from "./annotations/Label.sol";
|
|
9
9
|
import { Schema } from "./annotations/Schema.sol";
|
|
10
|
-
import { AccessDenied, AdminAccess, CallerAccess, CommanderAccess, CommanderNotAllowed, GuardianAccess, NodeAccess, TrustAccess } from "./core/Access.sol";
|
|
10
|
+
import { AccessDenied, AdminAccess, CallerAccess, CommanderAccess, CommanderNotAllowed, enforceSender, GuardianAccess, NodeAccess, TrustAccess } from "./core/Access.sol";
|
|
11
11
|
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";
|
|
@@ -18,7 +18,7 @@ import { 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";
|
|
21
|
-
import { AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Position, Tx } from "./core/Types.sol";
|
|
21
|
+
import { AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Debt, Position, Tx } from "./core/Types.sol";
|
|
22
22
|
import { Validator } from "./core/Validator.sol";
|
|
23
23
|
|
|
24
24
|
|
package/Endpoints.sol
CHANGED
|
@@ -18,7 +18,14 @@ import {Deposit, DepositHook, DepositPayable, DepositPayableHook} from "./comman
|
|
|
18
18
|
import {Payout, PayoutHook} from "./commands/Payout.sol";
|
|
19
19
|
import {Provision, ProvisionHook, ProvisionPayable, ProvisionPayableHook} from "./commands/Provision.sol";
|
|
20
20
|
import {RecoverPayable, RecoverPayableHook} from "./commands/Recover.sol";
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
Repay,
|
|
23
|
+
RepayInternal,
|
|
24
|
+
RepayPayable,
|
|
25
|
+
RepayPayableHook,
|
|
26
|
+
RepayPosition,
|
|
27
|
+
RepayPositionPayable
|
|
28
|
+
} from "./commands/Repay.sol";
|
|
22
29
|
import {RelayPayable, RelayBalancePayable, RelayPayableHook} from "./commands/Relay.sol";
|
|
23
30
|
import {Settle, SettlePayable, SettlePayableHook, SettleInternal} from "./commands/Settle.sol";
|
|
24
31
|
import {Withdraw, WithdrawHook} from "./commands/Withdraw.sol";
|
package/README.md
CHANGED
|
@@ -265,22 +265,24 @@ and return it, forward it intact, or revert. A command must never succeed while
|
|
|
265
265
|
silently ignoring or dropping supplied state. Commands that declare
|
|
266
266
|
`Specs.Empty` state therefore reject any non-empty state, while commands that
|
|
267
267
|
accept state validate the complete stream against their declared state schema.
|
|
268
|
-
This is especially important for `#position`, because dropping
|
|
269
|
-
silently discard
|
|
270
|
-
|
|
271
|
-
The input carries instructions; the state carries live value. While a
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
268
|
+
This is especially important for `#debt` and `#position`, because dropping
|
|
269
|
+
either could silently discard an outstanding debt requirement.
|
|
270
|
+
|
|
271
|
+
The input carries instructions; the state carries live value. While a sequence
|
|
272
|
+
of commands executes, `#balance`, `#debt`, `#custody`, and `#position` blocks in
|
|
273
|
+
the state are the value being moved — produced by one command, consumed by the
|
|
274
|
+
next. Balance carries `{ asset, amount }`, debt carries `{ liability, debt }`,
|
|
275
|
+
and position carries their flat combination
|
|
275
276
|
`{ asset, amount, liability, debt }`.
|
|
276
277
|
|
|
277
|
-
`#position`
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
278
|
+
`#debt` and `#position` are general live state rather than persisted
|
|
279
|
+
lending-specific debt records. Debt carries value owed or required; position
|
|
280
|
+
pairs that liability with value acquired or controlled. A command may preserve
|
|
281
|
+
or replace either side and return the resulting state for the next step;
|
|
282
|
+
`settle` terminally consumes a position pair. This supports swaps,
|
|
281
283
|
borrowing, refinancing, collateral changes, callback obligations, cross-host
|
|
282
|
-
claims, fees, netting, and other multi-step operations.
|
|
283
|
-
transient
|
|
284
|
+
claims, fees, netting, and other multi-step operations. Debt and position are
|
|
285
|
+
transient representations and do not themselves create or erase an obligation
|
|
284
286
|
recorded by an external system.
|
|
285
287
|
|
|
286
288
|
The standard `Deposit` mixin shows the canonical shape: open and validate both
|
|
@@ -330,7 +332,9 @@ abstract contract MyCommand is CommandBase {
|
|
|
330
332
|
|
|
331
333
|
The final argument is a packed flags byte. Pass `0` for an ordinary endpoint,
|
|
332
334
|
or compose values such as `Flags.Funded`, `Flags.Admin`, and
|
|
333
|
-
`Flags.AdminFunded` from the command or endpoint package entry point.
|
|
335
|
+
`Flags.AdminFunded` from the command or endpoint package entry point. Bits 6
|
|
336
|
+
and 7 are reserved for endpoint-defined custom flags. Bits 2 through 5 remain
|
|
337
|
+
reserved for future protocol flags.
|
|
334
338
|
|
|
335
339
|
The standard commands cover the common ledger movements: `deposit` and
|
|
336
340
|
`depositPayable` (external funds in), `settlePayable` (funded settlement),
|
|
@@ -338,7 +342,9 @@ The standard commands cover the common ledger movements: `deposit` and
|
|
|
338
342
|
`debitAccount` and `creditAccount` (internal movements), `payout` (deliver
|
|
339
343
|
state to other accounts), `allocate` (turn balance state into custody),
|
|
340
344
|
`provision` (provision custody from an external allocation), `settle` (consume
|
|
341
|
-
asset-liability position state), `
|
|
345
|
+
asset-liability position state), `repay` and `repayPayable` (consume standalone
|
|
346
|
+
debt state), `repayPosition` and `repayPositionPayable` (repay a position's debt
|
|
347
|
+
and return its asset as balance state), `relayPayable` (relay a pipeline without
|
|
342
348
|
state), and `relayBalancePayable` (relay balance state and a pipeline to another
|
|
343
349
|
portal).
|
|
344
350
|
|
|
@@ -384,12 +390,12 @@ portal adapter (on EVM, the low 128 bits are native value in wei, drawn from a
|
|
|
384
390
|
shared budget), so the same pipeline bytes are meaningful to every port.
|
|
385
391
|
|
|
386
392
|
Hosts that implement a pipeline locally can inherit `DebitAccountInternal`,
|
|
387
|
-
`CreditAccountInternal`, and `
|
|
388
|
-
endpoints while routing their local command IDs through
|
|
389
|
-
`executeCreditAccount`,
|
|
390
|
-
memory-backed pipeline state directly
|
|
391
|
-
step value into each adapter; all
|
|
392
|
-
commands are non-funded.
|
|
393
|
+
`CreditAccountInternal`, `SettleInternal`, and `RepayInternal` to advertise the
|
|
394
|
+
canonical command endpoints while routing their local command IDs through
|
|
395
|
+
`executeDebitAccount`, `executeCreditAccount`, `executeSettle`, and
|
|
396
|
+
`executeRepay`. These adapters consume the memory-backed pipeline state directly
|
|
397
|
+
and avoid an external self-call. Pass the step value into each adapter; all four
|
|
398
|
+
reject nonzero value because the commands are non-funded.
|
|
393
399
|
|
|
394
400
|
Positions also support backward-composed pipelines. In an exact-output route,
|
|
395
401
|
the asset side can represent the desired result while the liability side
|
package/Utils.sol
CHANGED
|
@@ -12,7 +12,7 @@ import { ECDSA } from "./utils/ECDSA.sol";
|
|
|
12
12
|
import { Ids } from "./utils/Ids.sol";
|
|
13
13
|
import { Nodes } from "./utils/Nodes.sol";
|
|
14
14
|
import { Layout } from "./utils/Layout.sol";
|
|
15
|
-
import { addrOr, applyBps, beforeBps, bytes32ToInt, bytes32ToString, clear8, clear16, clear32, clear64, divisible, ensureAddr, hash32, intToBytes32, isFamily, matchesBase, MAX_BPS, max8, max16, max24, max32, max40, max64, max96, max128, max160, NotDivisible, replace8, replace16, replace32, replace64, retryTicket, toLocalBase, toUnspecifiedBase, ValueOverflow, ZeroAddress } from "./utils/Utils.sol";
|
|
15
|
+
import { addrOr, applyBps, beforeBps, bytes32ToInt, bytes32ToString, clear8, clear16, clear32, clear64, divisible, ensureAddr, ensureContract, hash32, intToBytes32, InvalidContract, isFamily, matchesBase, MAX_BPS, max8, max16, max24, max32, max40, max64, max96, max128, max160, NotDivisible, replace8, replace16, replace32, replace64, retryTicket, toLocalBase, toUnspecifiedBase, ValueOverflow, ZeroAddress } from "./utils/Utils.sol";
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
|
package/annotations/Schema.sol
CHANGED
|
@@ -18,13 +18,7 @@ abstract contract Schema is Runtime, AnnotationEvent {
|
|
|
18
18
|
/// @param hint Initial per-block payload capacity.
|
|
19
19
|
/// @param body Schema DSL string describing the block payload body.
|
|
20
20
|
/// @return spec The context-local block specification.
|
|
21
|
-
function schema(
|
|
22
|
-
uint32 key,
|
|
23
|
-
uint32 min,
|
|
24
|
-
uint32 max,
|
|
25
|
-
uint32 hint,
|
|
26
|
-
string memory body
|
|
27
|
-
) internal returns (uint spec) {
|
|
21
|
+
function schema(uint32 key, uint32 min, uint32 max, uint32 hint, string memory body) internal returns (uint spec) {
|
|
28
22
|
return schema(key, min, max, hint, body, bytes32(0));
|
|
29
23
|
}
|
|
30
24
|
|
package/codec/Blocks.sol
CHANGED
|
@@ -382,6 +382,22 @@ library Blocks {
|
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
384
|
|
|
385
|
+
/// @notice Write a DEBT block at `i`.
|
|
386
|
+
/// @dev DANGER: Unchecked memory write. Reserve `Sizes.B64` bytes first.
|
|
387
|
+
/// @param dst Destination buffer.
|
|
388
|
+
/// @param i Relative write position.
|
|
389
|
+
/// @param liability Liability identifier to encode.
|
|
390
|
+
/// @param debt Debt quantity to encode.
|
|
391
|
+
function writeDebt(bytes memory dst, uint i, bytes32 liability, uint debt) internal pure {
|
|
392
|
+
uint spec = Specs.Debt;
|
|
393
|
+
assembly ("memory-safe") {
|
|
394
|
+
let p := add(add(dst, 0x20), i)
|
|
395
|
+
mstore(p, spec)
|
|
396
|
+
mstore(add(p, 0x08), liability)
|
|
397
|
+
mstore(add(p, 0x28), debt)
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
385
401
|
/// @notice Write a HOST_ASSET block at `i`.
|
|
386
402
|
/// @dev DANGER: Unchecked memory write. Reserve `Sizes.B64` bytes first.
|
|
387
403
|
/// @param dst Destination buffer.
|
|
@@ -1014,14 +1030,44 @@ library Blocks {
|
|
|
1014
1030
|
|
|
1015
1031
|
// Raw reads
|
|
1016
1032
|
|
|
1033
|
+
/// @notice Read one byte from an absolute calldata position.
|
|
1034
|
+
/// @dev DANGER: Unchecked calldata read. Values beyond calldata are zero-padded.
|
|
1035
|
+
/// @param abs Absolute calldata position.
|
|
1036
|
+
/// @return value Decoded one-byte value.
|
|
1037
|
+
function read1(uint abs) internal pure returns (bytes1 value) {
|
|
1038
|
+
return bytes1(read32(abs));
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/// @notice Read two bytes from an absolute calldata position.
|
|
1042
|
+
/// @dev DANGER: Unchecked calldata read. Values beyond calldata are zero-padded.
|
|
1043
|
+
/// @param abs Absolute calldata position.
|
|
1044
|
+
/// @return value Decoded two-byte value.
|
|
1045
|
+
function read2(uint abs) internal pure returns (bytes2 value) {
|
|
1046
|
+
return bytes2(read32(abs));
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1017
1049
|
/// @notice Read four bytes from an absolute calldata position.
|
|
1018
1050
|
/// @dev DANGER: Unchecked calldata read. Values beyond calldata are zero-padded.
|
|
1019
1051
|
/// @param abs Absolute calldata position.
|
|
1020
1052
|
/// @return value Decoded four-byte value.
|
|
1021
1053
|
function read4(uint abs) internal pure returns (bytes4 value) {
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1054
|
+
return bytes4(read32(abs));
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
/// @notice Read eight bytes from an absolute calldata position.
|
|
1058
|
+
/// @dev DANGER: Unchecked calldata read. Values beyond calldata are zero-padded.
|
|
1059
|
+
/// @param abs Absolute calldata position.
|
|
1060
|
+
/// @return value Decoded eight-byte value.
|
|
1061
|
+
function read8(uint abs) internal pure returns (bytes8 value) {
|
|
1062
|
+
return bytes8(read32(abs));
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
/// @notice Read sixteen bytes from an absolute calldata position.
|
|
1066
|
+
/// @dev DANGER: Unchecked calldata read. Values beyond calldata are zero-padded.
|
|
1067
|
+
/// @param abs Absolute calldata position.
|
|
1068
|
+
/// @return value Decoded sixteen-byte value.
|
|
1069
|
+
function read16(uint abs) internal pure returns (bytes16 value) {
|
|
1070
|
+
return bytes16(read32(abs));
|
|
1025
1071
|
}
|
|
1026
1072
|
|
|
1027
1073
|
/// @notice Read one word from an absolute calldata position.
|
|
@@ -1322,6 +1368,22 @@ library Blocks {
|
|
|
1322
1368
|
}
|
|
1323
1369
|
}
|
|
1324
1370
|
|
|
1371
|
+
/// @notice Decode a low-level fixed-width DEBT block at `abs`.
|
|
1372
|
+
/// @param abs Absolute block position.
|
|
1373
|
+
/// @return liability Decoded liability identifier.
|
|
1374
|
+
/// @return debt Decoded debt quantity.
|
|
1375
|
+
function unpackDebt(uint abs) internal pure returns (bytes32 liability, uint debt) {
|
|
1376
|
+
uint head;
|
|
1377
|
+
assembly ("memory-safe") {
|
|
1378
|
+
head := calldataload(abs)
|
|
1379
|
+
}
|
|
1380
|
+
if (head >> 192 != Specs.Debt >> 192) revert InvalidBlock();
|
|
1381
|
+
assembly ("memory-safe") {
|
|
1382
|
+
liability := calldataload(add(abs, 0x08))
|
|
1383
|
+
debt := calldataload(add(abs, 0x28))
|
|
1384
|
+
}
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1325
1387
|
/// @notice Decode a low-level fixed-width ACCOUNT_ASSET block at `abs`.
|
|
1326
1388
|
/// @param abs Absolute block position.
|
|
1327
1389
|
/// @return account Decoded account identifier.
|
|
@@ -1919,6 +1981,15 @@ library Blocks {
|
|
|
1919
1981
|
writeBalance(value, 0, asset, amount);
|
|
1920
1982
|
}
|
|
1921
1983
|
|
|
1984
|
+
/// @notice Encode a DEBT block.
|
|
1985
|
+
/// @param liability Liability identifier.
|
|
1986
|
+
/// @param debt Debt quantity.
|
|
1987
|
+
/// @return value Encoded DEBT block bytes.
|
|
1988
|
+
function createDebt(bytes32 liability, uint debt) internal pure returns (bytes memory value) {
|
|
1989
|
+
value = allocate(Sizes.Debt);
|
|
1990
|
+
writeDebt(value, 0, liability, debt);
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1922
1993
|
/// @notice Encode a CUSTODY block.
|
|
1923
1994
|
/// @param host Host node ID holding the custody.
|
|
1924
1995
|
/// @param asset Asset identifier.
|
package/codec/Decoders.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, Position, Tx} from "../core/Types.sol";
|
|
4
|
+
import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, Debt, Position, Tx} from "../core/Types.sol";
|
|
5
5
|
import {Blocks} from "./Blocks.sol";
|
|
6
6
|
import {Sizes, Specs} from "./Specs.sol";
|
|
7
7
|
import {Cursors, Cur} from "../utils/Cursors.sol";
|
|
@@ -427,6 +427,16 @@ library Decoders {
|
|
|
427
427
|
(asset, amount) = Blocks.unpackBalance(abs);
|
|
428
428
|
}
|
|
429
429
|
|
|
430
|
+
/// @notice Decode and consume one DEBT block.
|
|
431
|
+
/// @param cur Cursor advanced past the block.
|
|
432
|
+
/// @return liability Decoded liability identifier.
|
|
433
|
+
/// @return debt Decoded debt quantity.
|
|
434
|
+
function unpackDebt(Cur memory cur) internal pure returns (bytes32 liability, uint debt) {
|
|
435
|
+
uint abs;
|
|
436
|
+
(cur.state, abs) = cur.state.consume(Sizes.Debt);
|
|
437
|
+
(liability, debt) = Blocks.unpackDebt(abs);
|
|
438
|
+
}
|
|
439
|
+
|
|
430
440
|
/// @notice Decode one BALANCE block and associate it with `host`.
|
|
431
441
|
/// @param cur Cursor advanced past the block.
|
|
432
442
|
/// @param host Host identifier associated with the balance.
|
|
@@ -614,6 +624,13 @@ library Decoders {
|
|
|
614
624
|
(value.asset, value.amount) = unpackBalance(cur);
|
|
615
625
|
}
|
|
616
626
|
|
|
627
|
+
/// @notice Decode one DEBT block into its structured value.
|
|
628
|
+
/// @param cur Cursor advanced past the block.
|
|
629
|
+
/// @return value Structured liability and debt.
|
|
630
|
+
function unpackDebtValue(Cur memory cur) internal pure returns (Debt memory value) {
|
|
631
|
+
(value.liability, value.debt) = unpackDebt(cur);
|
|
632
|
+
}
|
|
633
|
+
|
|
617
634
|
/// @notice Decode and consume one HOST_ACCOUNT_ASSET block.
|
|
618
635
|
/// @param cur Cursor advanced past the block.
|
|
619
636
|
/// @return host Decoded host identifier.
|
package/codec/Descriptors.sol
CHANGED
|
@@ -6,6 +6,7 @@ import {Lanes} from "../utils/Lanes.sol";
|
|
|
6
6
|
|
|
7
7
|
/// @title Flags
|
|
8
8
|
/// @notice Packed endpoint behavior flags.
|
|
9
|
+
/// @dev Bits 6 and 7 are reserved for endpoint-defined custom flags.
|
|
9
10
|
library Flags {
|
|
10
11
|
/// @dev Endpoint accepts nonzero native value.
|
|
11
12
|
uint8 internal constant Funded = 1 << 0;
|
|
@@ -27,7 +28,8 @@ library Descriptors {
|
|
|
27
28
|
/// `[output key:4][min:4][max:4][hint:3][stride:1]`
|
|
28
29
|
/// `[reserved:4]`
|
|
29
30
|
/// `[transactions:1]`
|
|
30
|
-
/// `[flags:1]`. Flag bits: funded = 0, admin = 1
|
|
31
|
+
/// `[flags:1]`. Flag bits: funded = 0, admin = 1; bits 6 and 7 are
|
|
32
|
+
/// reserved for endpoint-defined custom flags.
|
|
31
33
|
/// @param state State lane specification.
|
|
32
34
|
/// @param input Direct input lane specification.
|
|
33
35
|
/// @param output Output writer specification.
|
package/codec/Keys.sol
CHANGED
|
@@ -13,6 +13,8 @@ library Keys {
|
|
|
13
13
|
bytes4 constant Amount = bytes4(keccak256("#amount"));
|
|
14
14
|
/// @dev Ledger balance - (bytes32 asset, uint amount)
|
|
15
15
|
bytes4 constant Balance = bytes4(keccak256("#balance"));
|
|
16
|
+
/// @dev Liability-only debt state - (bytes32 liability, uint debt)
|
|
17
|
+
bytes4 constant Debt = bytes4(keccak256("#debt"));
|
|
16
18
|
/// @dev Host-scoped input amount - (uint host, bytes32 asset, uint amount)
|
|
17
19
|
bytes4 constant Allocation = bytes4(keccak256("#allocation"));
|
|
18
20
|
/// @dev Host-scoped allowance cap - (uint host, bytes32 asset, uint amount)
|
package/codec/Readers.sol
CHANGED
|
@@ -133,6 +133,18 @@ library Readers {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
+
/// @notice Consume a DEBT block and return its fields.
|
|
137
|
+
/// @param cur Reader; advanced past the block.
|
|
138
|
+
/// @return liability Liability identifier.
|
|
139
|
+
/// @return debt Debt quantity.
|
|
140
|
+
function unpackDebt(Reader memory cur) internal pure returns (bytes32 liability, uint debt) {
|
|
141
|
+
uint abs = consume(cur, Keys.Debt, 64, 64);
|
|
142
|
+
assembly ("memory-safe") {
|
|
143
|
+
liability := mload(abs)
|
|
144
|
+
debt := mload(add(abs, 0x20))
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
136
148
|
/// @notice Consume a HOST_ASSET block and return its fields.
|
|
137
149
|
/// @param cur Reader; advanced past the block.
|
|
138
150
|
/// @return host Host identifier.
|
package/codec/Schema.sol
CHANGED
|
@@ -53,12 +53,12 @@ pragma solidity ^0.8.33;
|
|
|
53
53
|
// - command input and state streams are each a single run of blocks under the
|
|
54
54
|
// current protocol convention; the block format may support other shapes in
|
|
55
55
|
// future protocol surfaces
|
|
56
|
-
// - `balance(...)`, `custody(...)`, and `position(...)` are live, linear state in the active command pipeline
|
|
56
|
+
// - `balance(...)`, `debt(...)`, `custody(...)`, and `position(...)` are live, linear state in the active command pipeline
|
|
57
57
|
// - pipeline state belongs to the active account while the pipeline is executing
|
|
58
|
-
// - while a balance or custody is in-flight as pipeline state, it is not simultaneously persisted
|
|
58
|
+
// - while a balance, debt, or custody is in-flight as pipeline state, it is not simultaneously persisted
|
|
59
59
|
// in another ledger/store by this protocol
|
|
60
|
-
// - a position pairs live
|
|
61
|
-
// - position state
|
|
60
|
+
// - debt carries only a live liability side; position pairs live balance and debt sides
|
|
61
|
+
// - debt and position state are transient and do not themselves create or erase an externally persisted obligation
|
|
62
62
|
// - positions support backward composition, but pipeline steps always execute in encoded order
|
|
63
63
|
// - commands must preserve, transform, settle, or intentionally consume pipeline state
|
|
64
64
|
// - input blocks such as `amount(...)`, `allocation(...)`, and `allowance(...)`
|
|
@@ -89,6 +89,7 @@ library Schemas {
|
|
|
89
89
|
|
|
90
90
|
string constant Amount = "bytes32 asset, uint amount";
|
|
91
91
|
string constant Balance = "bytes32 asset, uint amount";
|
|
92
|
+
string constant Debt = "bytes32 liability, uint debt";
|
|
92
93
|
string constant AccountAsset = "bytes32 account, bytes32 asset";
|
|
93
94
|
string constant HostAsset = "uint host, bytes32 asset";
|
|
94
95
|
|
package/codec/Specs.sol
CHANGED
|
@@ -27,6 +27,8 @@ library Sizes {
|
|
|
27
27
|
uint constant Amount = B64;
|
|
28
28
|
/// @dev BALANCE block: 8 header + 32 asset + 32 amount = 72 bytes
|
|
29
29
|
uint constant Balance = B64;
|
|
30
|
+
/// @dev DEBT block: 8 header + 32 liability + 32 debt = 72 bytes
|
|
31
|
+
uint constant Debt = B64;
|
|
30
32
|
/// @dev HOST_ASSET block: 8 header + 32 host + 32 asset = 72 bytes
|
|
31
33
|
uint constant HostAsset = B64;
|
|
32
34
|
/// @dev ALLOCATION/CUSTODY block: 8 header + 32 host + 32 asset + 32 amount = 104 bytes
|
|
@@ -63,6 +65,7 @@ library Specs {
|
|
|
63
65
|
uint constant Empty = uint(bytes32(Keys.Empty));
|
|
64
66
|
uint constant Amount = uint(bytes32(Keys.Amount)) | Exact64;
|
|
65
67
|
uint constant Balance = uint(bytes32(Keys.Balance)) | Exact64;
|
|
68
|
+
uint constant Debt = uint(bytes32(Keys.Debt)) | Exact64;
|
|
66
69
|
uint constant Allocation = uint(bytes32(Keys.Allocation)) | Exact96;
|
|
67
70
|
uint constant Allowance = uint(bytes32(Keys.Allowance)) | Exact96;
|
|
68
71
|
uint constant Custody = uint(bytes32(Keys.Custody)) | Exact96;
|
package/codec/Writers.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AssetAmount, AccountAmount, HostAmount, Position, Tx} from "../core/Types.sol";
|
|
4
|
+
import {AssetAmount, AccountAmount, HostAmount, Debt, Position, Tx} from "../core/Types.sol";
|
|
5
5
|
import {Blocks} from "./Blocks.sol";
|
|
6
6
|
import {Buffers} from "./Buffers.sol";
|
|
7
7
|
import {Sizes, Specs} from "./Specs.sol";
|
|
@@ -204,6 +204,17 @@ library Writers {
|
|
|
204
204
|
appendBalance(writer, value.asset, value.amount);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
/// @notice Append a DEBT block.
|
|
208
|
+
function appendDebt(Writer memory writer, bytes32 liability, uint debt) internal pure {
|
|
209
|
+
uint i = reserve(writer, Sizes.Debt);
|
|
210
|
+
Blocks.writeDebt(writer.dst, i, liability, debt);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/// @notice Append a structured DEBT value.
|
|
214
|
+
function appendDebt(Writer memory writer, Debt memory value) internal pure {
|
|
215
|
+
appendDebt(writer, value.liability, value.debt);
|
|
216
|
+
}
|
|
217
|
+
|
|
207
218
|
/// @notice Append an ACCOUNT_ASSET block.
|
|
208
219
|
/// @param writer Destination writer.
|
|
209
220
|
/// @param account Account identifier to encode.
|
package/commands/Repay.sol
CHANGED
|
@@ -5,10 +5,13 @@ import {Execution, Executions, CommandBase, Flags, Lanes, Specs} from "./Base.so
|
|
|
5
5
|
import {RepayHook} from "../core/Settlement.sol";
|
|
6
6
|
import {Action} from "../annotations/Action.sol";
|
|
7
7
|
import {Actions} from "../utils/Actions.sol";
|
|
8
|
+
import {Blocks} from "../codec/Blocks.sol";
|
|
9
|
+
import {Reader, Readers} from "../codec/Readers.sol";
|
|
8
10
|
|
|
9
11
|
using Executions for Execution;
|
|
12
|
+
using Readers for Reader;
|
|
10
13
|
|
|
11
|
-
/// @notice Hook implemented by hosts that repay
|
|
14
|
+
/// @notice Hook implemented by hosts that repay liabilities using native value.
|
|
12
15
|
abstract contract RepayPayableHook {
|
|
13
16
|
/// @notice Override to repay one liability for `account` with a shared value budget.
|
|
14
17
|
/// @param account Account whose liability is being repaid.
|
|
@@ -19,21 +22,84 @@ abstract contract RepayPayableHook {
|
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
/// @title Repay
|
|
22
|
-
/// @notice Command that
|
|
25
|
+
/// @notice Command that consumes DEBT state by repaying each liability.
|
|
23
26
|
abstract contract Repay is CommandBase, RepayHook, Action {
|
|
24
27
|
uint private immutable descriptor;
|
|
28
|
+
uint private immutable id;
|
|
29
|
+
|
|
30
|
+
constructor() {
|
|
31
|
+
(id, descriptor) = command("repay", Specs.Debt, Specs.Empty, Specs.Empty, 0, 0);
|
|
32
|
+
action(id, Actions.Repay);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/// @notice Return the registered REPAY command ID.
|
|
36
|
+
function repayId() internal view returns (uint) {
|
|
37
|
+
return id;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/// @notice Repay each liability in the DEBT state stream.
|
|
41
|
+
/// @param context Command context carrying the DEBT state stream.
|
|
42
|
+
/// @return Empty output state.
|
|
43
|
+
/// @return Empty transaction stream.
|
|
44
|
+
function repay(
|
|
45
|
+
bytes calldata context
|
|
46
|
+
) external onlyCommand returns (bytes memory, bytes memory) {
|
|
47
|
+
Execution memory exec = openCommand(context, descriptor, 0);
|
|
48
|
+
|
|
49
|
+
while (exec.more()) {
|
|
50
|
+
(bytes32 liability, uint debt) = exec.unpackDebt(Lanes.State);
|
|
51
|
+
repay(exec.account, liability, debt);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return closeCommand(exec);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @title RepayPayable
|
|
59
|
+
/// @notice Funded command that consumes DEBT state by repaying each liability.
|
|
60
|
+
abstract contract RepayPayable is CommandBase, RepayPayableHook, Action {
|
|
61
|
+
uint private immutable descriptor;
|
|
25
62
|
|
|
26
63
|
constructor() {
|
|
27
64
|
uint id;
|
|
28
|
-
(id, descriptor) = command("
|
|
29
|
-
action(id, Actions.
|
|
65
|
+
(id, descriptor) = command("repayPayable", Specs.Debt, Specs.Empty, Specs.Empty, 0, Flags.Funded);
|
|
66
|
+
action(id, Actions.Repay);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// @notice Repay each liability in the DEBT state stream.
|
|
70
|
+
/// @param context Command context carrying the DEBT state stream.
|
|
71
|
+
/// @return Empty output state.
|
|
72
|
+
/// @return Remaining native value as a refund transaction stream.
|
|
73
|
+
function repayPayable(
|
|
74
|
+
bytes calldata context
|
|
75
|
+
) external payable onlyCommand returns (bytes memory, bytes memory) {
|
|
76
|
+
Execution memory exec = openCommand(context, descriptor, 0);
|
|
77
|
+
|
|
78
|
+
while (exec.more()) {
|
|
79
|
+
(bytes32 liability, uint debt) = exec.unpackDebt(Lanes.State);
|
|
80
|
+
repay(exec.account, liability, debt, exec);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return closeCommand(exec);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/// @title RepayPosition
|
|
88
|
+
/// @notice Command that repays POSITION liabilities and returns their assets as BALANCE state.
|
|
89
|
+
abstract contract RepayPosition is CommandBase, RepayHook, Action {
|
|
90
|
+
uint private immutable descriptor;
|
|
91
|
+
|
|
92
|
+
constructor() {
|
|
93
|
+
uint id;
|
|
94
|
+
(id, descriptor) = command("repayPosition", Specs.Position, Specs.Empty, Specs.Balance, 0, 0);
|
|
95
|
+
action(id, Actions.Repay);
|
|
30
96
|
}
|
|
31
97
|
|
|
32
98
|
/// @notice Repay each POSITION liability and return its asset as BALANCE state.
|
|
33
99
|
/// @param context Command context carrying the POSITION state stream.
|
|
34
100
|
/// @return BALANCE output state containing each released asset side.
|
|
35
101
|
/// @return Empty transaction stream.
|
|
36
|
-
function
|
|
102
|
+
function repayPosition(
|
|
37
103
|
bytes calldata context
|
|
38
104
|
) external onlyCommand returns (bytes memory, bytes memory) {
|
|
39
105
|
Execution memory exec = openCommand(context, descriptor, 0);
|
|
@@ -48,22 +114,24 @@ abstract contract Repay is CommandBase, RepayHook, Action {
|
|
|
48
114
|
}
|
|
49
115
|
}
|
|
50
116
|
|
|
51
|
-
/// @title
|
|
117
|
+
/// @title RepayPositionPayable
|
|
52
118
|
/// @notice Funded command that repays POSITION liabilities and returns their assets as BALANCE state.
|
|
53
|
-
abstract contract
|
|
119
|
+
abstract contract RepayPositionPayable is CommandBase, RepayPayableHook, Action {
|
|
54
120
|
uint private immutable descriptor;
|
|
55
121
|
|
|
56
122
|
constructor() {
|
|
57
123
|
uint id;
|
|
58
|
-
(id, descriptor) = command(
|
|
59
|
-
|
|
124
|
+
(id, descriptor) = command(
|
|
125
|
+
"repayPositionPayable", Specs.Position, Specs.Empty, Specs.Balance, 0, Flags.Funded
|
|
126
|
+
);
|
|
127
|
+
action(id, Actions.Repay);
|
|
60
128
|
}
|
|
61
129
|
|
|
62
130
|
/// @notice Repay each POSITION liability and return its asset as BALANCE state.
|
|
63
131
|
/// @param context Command context carrying the POSITION state stream.
|
|
64
132
|
/// @return BALANCE output state containing each released asset side.
|
|
65
133
|
/// @return Remaining native value as a refund transaction stream.
|
|
66
|
-
function
|
|
134
|
+
function repayPositionPayable(
|
|
67
135
|
bytes calldata context
|
|
68
136
|
) external payable onlyCommand returns (bytes memory, bytes memory) {
|
|
69
137
|
Execution memory exec = openCommand(context, descriptor, 0);
|
|
@@ -77,3 +145,35 @@ abstract contract RepayPayable is CommandBase, RepayPayableHook, Action {
|
|
|
77
145
|
return closeCommand(exec);
|
|
78
146
|
}
|
|
79
147
|
}
|
|
148
|
+
|
|
149
|
+
/// @title RepayInternal
|
|
150
|
+
/// @notice Extends the advertised repay command with memory-state pipeline dispatch.
|
|
151
|
+
/// @dev This adapter is not a separate command. It uses the command ID and repayment hook
|
|
152
|
+
/// inherited from `Repay` while accepting the state location used by `Pipeline`.
|
|
153
|
+
abstract contract RepayInternal is Repay {
|
|
154
|
+
/// @notice Execute the inherited repay command from an internal pipeline.
|
|
155
|
+
/// @param account Account whose liabilities are repaid.
|
|
156
|
+
/// @param state DEBT block stream held in pipeline memory.
|
|
157
|
+
/// @param input Empty input required by the command schema.
|
|
158
|
+
/// @param value Native value assigned to the command; must be zero.
|
|
159
|
+
/// @return output Empty output state.
|
|
160
|
+
/// @return transactions Empty transaction stream.
|
|
161
|
+
function executeRepay(
|
|
162
|
+
bytes32 account,
|
|
163
|
+
bytes memory state,
|
|
164
|
+
bytes calldata input,
|
|
165
|
+
uint128 value
|
|
166
|
+
) internal returns (bytes memory, bytes memory) {
|
|
167
|
+
if (value != 0) revert ValueNotAllowed();
|
|
168
|
+
if (input.length != 0) revert Executions.ZeroStride();
|
|
169
|
+
if (state.length == 0) revert Blocks.EmptyRun();
|
|
170
|
+
|
|
171
|
+
Reader memory reader = Readers.open(state);
|
|
172
|
+
while (reader.more()) {
|
|
173
|
+
(bytes32 liability, uint debt) = reader.unpackDebt();
|
|
174
|
+
repay(account, liability, debt);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return ("", "");
|
|
178
|
+
}
|
|
179
|
+
}
|
package/core/Access.sol
CHANGED
|
@@ -12,6 +12,14 @@ import {addrOr} from "../utils/Utils.sol";
|
|
|
12
12
|
error AccessDenied();
|
|
13
13
|
error CommanderNotAllowed();
|
|
14
14
|
|
|
15
|
+
/// @notice Assert that `msg.sender` equals `expected` and return it.
|
|
16
|
+
/// @param expected Address required to be the current message sender.
|
|
17
|
+
/// @return The validated sender address.
|
|
18
|
+
function enforceSender(address expected) view returns (address) {
|
|
19
|
+
if (msg.sender != expected) revert AccessDenied();
|
|
20
|
+
return expected;
|
|
21
|
+
}
|
|
22
|
+
|
|
15
23
|
/// @title CallerAccess
|
|
16
24
|
/// @notice Authorization capability required by command entrypoints.
|
|
17
25
|
abstract contract CallerAccess is Runtime {
|
package/core/Types.sol
CHANGED
|
@@ -67,6 +67,14 @@ struct HostAccountAmount {
|
|
|
67
67
|
uint amount;
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
+
/// @notice Liability and debt pair threaded as live pipeline state.
|
|
71
|
+
struct Debt {
|
|
72
|
+
/// @dev Identifier for the liability side.
|
|
73
|
+
bytes32 liability;
|
|
74
|
+
/// @dev Quantity owed on the liability side.
|
|
75
|
+
uint debt;
|
|
76
|
+
}
|
|
77
|
+
|
|
70
78
|
/// @notice Asset and liability pair threaded as live pipeline state.
|
|
71
79
|
struct Position {
|
|
72
80
|
/// @dev Identifier for the asset side.
|
package/execution/Execution.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, Position, Tx} from "../core/Types.sol";
|
|
4
|
+
import {AssetAmount, AccountAsset, HostAsset, AccountAmount, HostAmount, HostAccountAsset, Debt, Position, Tx} from "../core/Types.sol";
|
|
5
5
|
import {Blocks} from "../codec/Blocks.sol";
|
|
6
6
|
import {Buffers} from "../codec/Buffers.sol";
|
|
7
7
|
import {Sizes, Specs} from "../codec/Specs.sol";
|
|
@@ -528,6 +528,18 @@ library Executions {
|
|
|
528
528
|
(value.asset, value.amount) = unpackBalance(exec, lane);
|
|
529
529
|
}
|
|
530
530
|
|
|
531
|
+
/// @notice Decode and consume one DEBT block from `lane`.
|
|
532
|
+
function unpackDebt(Execution memory exec, uint8 lane) internal pure returns (bytes32 liability, uint debt) {
|
|
533
|
+
uint abs;
|
|
534
|
+
(exec.decoders, abs) = exec.decoders.consume(lane, Sizes.Debt);
|
|
535
|
+
(liability, debt) = Blocks.unpackDebt(abs);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
/// @notice Decode one DEBT block into its structured value.
|
|
539
|
+
function unpackDebtValue(Execution memory exec, uint8 lane) internal pure returns (Debt memory value) {
|
|
540
|
+
(value.liability, value.debt) = unpackDebt(exec, lane);
|
|
541
|
+
}
|
|
542
|
+
|
|
531
543
|
/// @notice Decode and consume one POSITION block from `lane`.
|
|
532
544
|
function unpackPosition(
|
|
533
545
|
Execution memory exec,
|
|
@@ -990,6 +1002,17 @@ library Executions {
|
|
|
990
1002
|
outputBalance(exec, value.asset, value.amount);
|
|
991
1003
|
}
|
|
992
1004
|
|
|
1005
|
+
/// @notice Append a DEBT block to execution output.
|
|
1006
|
+
function outputDebt(Execution memory exec, bytes32 liability, uint debt) internal pure {
|
|
1007
|
+
uint i = reserve(exec, Sizes.Debt);
|
|
1008
|
+
Blocks.writeDebt(exec.output, i, liability, debt);
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
/// @notice Append a structured DEBT value to execution output.
|
|
1012
|
+
function outputDebt(Execution memory exec, Debt memory value) internal pure {
|
|
1013
|
+
outputDebt(exec, value.liability, value.debt);
|
|
1014
|
+
}
|
|
1015
|
+
|
|
993
1016
|
/// @notice Append a POSITION block to execution output.
|
|
994
1017
|
function outputPosition(
|
|
995
1018
|
Execution memory exec,
|
package/package.json
CHANGED
package/utils/Utils.sol
CHANGED
|
@@ -10,6 +10,8 @@ error ValueOverflow();
|
|
|
10
10
|
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
|
+
/// @dev Thrown when an address does not contain deployed bytecode.
|
|
14
|
+
error InvalidContract();
|
|
13
15
|
|
|
14
16
|
/// @notice Assert that `value` fits in uint8 and return it as uint8.
|
|
15
17
|
function max8(uint value) pure returns (uint8) {
|
|
@@ -146,6 +148,14 @@ function ensureAddr(address addr) pure returns (address) {
|
|
|
146
148
|
return addr;
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
/// @notice Assert that `target` contains deployed bytecode and return it unchanged.
|
|
152
|
+
/// @dev Rejects EOAs, zero and future deployment addresses, contracts currently
|
|
153
|
+
/// under construction, and precompiles whose code length is zero.
|
|
154
|
+
function ensureContract(address target) view returns (address) {
|
|
155
|
+
if (target.code.length == 0) revert InvalidContract();
|
|
156
|
+
return target;
|
|
157
|
+
}
|
|
158
|
+
|
|
149
159
|
/// @notice Convert a signed integer to its 32-byte two's-complement representation.
|
|
150
160
|
function intToBytes32(int value) pure returns (bytes32) {
|
|
151
161
|
return bytes32(uint(value));
|