@rootzero/contracts 1.22.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.
Files changed (57) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/Codec.sol +1 -1
  3. package/Commands.sol +1 -1
  4. package/Core.sol +2 -2
  5. package/Endpoints.sol +10 -4
  6. package/Events.sol +1 -1
  7. package/README.md +40 -32
  8. package/Utils.sol +1 -1
  9. package/annotations/Action.sol +1 -1
  10. package/annotations/Label.sol +1 -1
  11. package/annotations/Schema.sol +2 -8
  12. package/codec/Blocks.sol +113 -33
  13. package/codec/Decoders.sol +18 -1
  14. package/codec/Descriptors.sol +3 -1
  15. package/codec/Keys.sol +2 -0
  16. package/codec/Readers.sol +12 -0
  17. package/codec/Schema.sol +5 -4
  18. package/codec/Specs.sol +3 -0
  19. package/codec/Writers.sol +12 -1
  20. package/commands/Allocate.sol +5 -8
  21. package/commands/Base.sol +29 -13
  22. package/commands/Burn.sol +5 -7
  23. package/commands/Credit.sol +5 -7
  24. package/commands/Debit.sol +5 -7
  25. package/commands/Deposit.sol +10 -14
  26. package/commands/Payout.sol +5 -8
  27. package/commands/Provision.sol +10 -14
  28. package/commands/Recover.sol +4 -6
  29. package/commands/Relay.sol +14 -21
  30. package/commands/Repay.sol +120 -24
  31. package/commands/Settle.sol +10 -14
  32. package/commands/Withdraw.sol +5 -7
  33. package/commands/admin/AllowAssets.sol +5 -7
  34. package/commands/admin/Allowance.sol +5 -7
  35. package/commands/admin/Annotate.sol +5 -7
  36. package/commands/admin/Appoint.sol +5 -7
  37. package/commands/admin/Authorize.sol +5 -7
  38. package/commands/admin/Base.sol +12 -3
  39. package/commands/admin/DenyAssets.sol +5 -7
  40. package/commands/admin/Dismiss.sol +5 -7
  41. package/commands/admin/Execute.sol +5 -7
  42. package/commands/admin/Unauthorize.sol +5 -7
  43. package/core/Access.sol +8 -0
  44. package/core/Calls.sol +72 -3
  45. package/core/Portal.sol +2 -2
  46. package/core/Types.sol +8 -0
  47. package/events/Positioned.sol +22 -0
  48. package/execution/Execution.sol +66 -1
  49. package/package.json +1 -1
  50. package/ports/Allowance.sol +22 -12
  51. package/ports/Assets.sol +99 -0
  52. package/utils/Cursors.sol +3 -3
  53. package/utils/Nodes.sol +1 -1
  54. package/utils/Utils.sol +41 -31
  55. package/events/Commander.sol +0 -19
  56. package/ports/AllowAssets.sol +0 -34
  57. package/ports/DenyAssets.sol +0 -34
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
- assembly ("memory-safe") {
1023
- value := calldataload(abs)
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.
@@ -1776,7 +1838,7 @@ library Blocks {
1776
1838
  /// @notice Encode an empty block.
1777
1839
  /// @param key Block type key.
1778
1840
  /// @return value Encoded empty block header.
1779
- function empty(bytes4 key) internal pure returns (bytes memory value) {
1841
+ function createEmpty(bytes4 key) internal pure returns (bytes memory value) {
1780
1842
  value = allocate(Sizes.Header);
1781
1843
  writeEmpty(value, 0, key);
1782
1844
  }
@@ -1801,28 +1863,28 @@ library Blocks {
1801
1863
  // Dynamic leaf factories
1802
1864
 
1803
1865
  /// @notice Encode a LIST block.
1804
- function list(bytes memory value) internal pure returns (bytes memory blockdata) {
1866
+ function createList(bytes memory value) internal pure returns (bytes memory blockdata) {
1805
1867
  uint len = max32(value.length);
1806
1868
  blockdata = allocate(Sizes.Header + len);
1807
1869
  writeList(blockdata, 0, value);
1808
1870
  }
1809
1871
 
1810
1872
  /// @notice Encode a LIST block by copying its payload from calldata.
1811
- function listCopy(bytes calldata value) internal pure returns (bytes memory blockdata) {
1873
+ function createListCopy(bytes calldata value) internal pure returns (bytes memory blockdata) {
1812
1874
  uint len = max32(value.length);
1813
1875
  blockdata = allocate(Sizes.Header + len);
1814
1876
  copyList(blockdata, 0, value);
1815
1877
  }
1816
1878
 
1817
1879
  /// @notice Encode an EVM block.
1818
- function evm(bytes memory value) internal pure returns (bytes memory blockdata) {
1880
+ function createEvm(bytes memory value) internal pure returns (bytes memory blockdata) {
1819
1881
  uint len = max32(value.length);
1820
1882
  blockdata = allocate(Sizes.Header + len);
1821
1883
  writeEvm(blockdata, 0, value);
1822
1884
  }
1823
1885
 
1824
1886
  /// @notice Encode an EVM block by copying its payload from calldata.
1825
- function evmCopy(bytes calldata value) internal pure returns (bytes memory blockdata) {
1887
+ function createEvmCopy(bytes calldata value) internal pure returns (bytes memory blockdata) {
1826
1888
  uint len = max32(value.length);
1827
1889
  blockdata = allocate(Sizes.Header + len);
1828
1890
  copyEvm(blockdata, 0, value);
@@ -1831,14 +1893,14 @@ library Blocks {
1831
1893
  /// @notice Encode a BYTES block with a raw payload.
1832
1894
  /// @param value Raw payload bytes.
1833
1895
  /// @return blockdata Encoded BYTES block bytes.
1834
- function data(bytes memory value) internal pure returns (bytes memory blockdata) {
1896
+ function createBytes(bytes memory value) internal pure returns (bytes memory blockdata) {
1835
1897
  uint len = max32(value.length);
1836
1898
  blockdata = allocate(Sizes.Header + len);
1837
1899
  writeBytes(blockdata, 0, value);
1838
1900
  }
1839
1901
 
1840
1902
  /// @notice Encode a BYTES block by copying its payload from calldata.
1841
- function dataCopy(bytes calldata value) internal pure returns (bytes memory blockdata) {
1903
+ function createBytesCopy(bytes calldata value) internal pure returns (bytes memory blockdata) {
1842
1904
  uint len = max32(value.length);
1843
1905
  blockdata = allocate(Sizes.Header + len);
1844
1906
  copyBytes(blockdata, 0, value);
@@ -1847,14 +1909,14 @@ library Blocks {
1847
1909
  /// @notice Encode a STRING block with a UTF-8 payload.
1848
1910
  /// @param value String payload.
1849
1911
  /// @return blockdata Encoded STRING block bytes.
1850
- function text(string memory value) internal pure returns (bytes memory blockdata) {
1912
+ function createString(string memory value) internal pure returns (bytes memory blockdata) {
1851
1913
  uint len = max32(bytes(value).length);
1852
1914
  blockdata = allocate(Sizes.Header + len);
1853
1915
  writeString(blockdata, 0, value);
1854
1916
  }
1855
1917
 
1856
1918
  /// @notice Encode a STRING block by copying its payload from calldata.
1857
- function textCopy(string calldata value) internal pure returns (bytes memory blockdata) {
1919
+ function createStringCopy(string calldata value) internal pure returns (bytes memory blockdata) {
1858
1920
  uint len = max32(bytes(value).length);
1859
1921
  blockdata = allocate(Sizes.Header + len);
1860
1922
  copyString(blockdata, 0, value);
@@ -1866,7 +1928,7 @@ library Blocks {
1866
1928
  /// @param namespace Label namespace.
1867
1929
  /// @param name Label text.
1868
1930
  /// @return value Encoded LABEL block bytes.
1869
- function label(bytes32 namespace, string memory name) internal pure returns (bytes memory value) {
1931
+ function createLabel(bytes32 namespace, string memory name) internal pure returns (bytes memory value) {
1870
1932
  uint len = max32(Sizes.B32 + bytes(name).length);
1871
1933
  value = allocate(Sizes.Header + len);
1872
1934
  writeLabel(value, 0, namespace, name);
@@ -1875,7 +1937,7 @@ library Blocks {
1875
1937
  /// @notice Encode an ACTION annotation block.
1876
1938
  /// @param actionid Canonical semantic action identifier.
1877
1939
  /// @return value Encoded ACTION block bytes.
1878
- function action(uint actionid) internal pure returns (bytes memory value) {
1940
+ function createAction(uint actionid) internal pure returns (bytes memory value) {
1879
1941
  value = allocate(Sizes.B32);
1880
1942
  write32(value, 0, Keys.Action, bytes32(actionid));
1881
1943
  }
@@ -1884,8 +1946,8 @@ library Blocks {
1884
1946
  /// @param spec Block specification.
1885
1947
  /// @param body Schema body.
1886
1948
  /// @return value Encoded SCHEMA block bytes.
1887
- function schema(uint spec, string memory body) internal pure returns (bytes memory value) {
1888
- return schema(spec, body, bytes32(0));
1949
+ function createSchema(uint spec, string memory body) internal pure returns (bytes memory value) {
1950
+ return createSchema(spec, body, bytes32(0));
1889
1951
  }
1890
1952
 
1891
1953
  /// @notice Encode a named SCHEMA block.
@@ -1893,7 +1955,7 @@ library Blocks {
1893
1955
  /// @param body Schema body.
1894
1956
  /// @param name Schema name.
1895
1957
  /// @return value Encoded SCHEMA block bytes.
1896
- function schema(uint spec, string memory body, bytes32 name) internal pure returns (bytes memory value) {
1958
+ function createSchema(uint spec, string memory body, bytes32 name) internal pure returns (bytes memory value) {
1897
1959
  uint len = max32(Sizes.B64 + bytes(body).length);
1898
1960
  value = allocate(Sizes.Header + len);
1899
1961
  writeSchema(value, 0, spec, body, name);
@@ -1901,21 +1963,39 @@ library Blocks {
1901
1963
 
1902
1964
  // Fixed-width factories
1903
1965
 
1966
+ /// @notice Encode an AMOUNT block.
1967
+ /// @param asset Asset identifier.
1968
+ /// @param amount Token amount.
1969
+ /// @return value Encoded AMOUNT block bytes.
1970
+ function createAmount(bytes32 asset, uint amount) internal pure returns (bytes memory value) {
1971
+ value = allocate(Sizes.Amount);
1972
+ writeAmount(value, 0, asset, amount);
1973
+ }
1974
+
1904
1975
  /// @notice Encode a BALANCE block.
1905
1976
  /// @param asset Asset identifier.
1906
1977
  /// @param amount Token amount.
1907
1978
  /// @return value Encoded BALANCE block bytes.
1908
- function balance(bytes32 asset, uint amount) internal pure returns (bytes memory value) {
1979
+ function createBalance(bytes32 asset, uint amount) internal pure returns (bytes memory value) {
1909
1980
  value = allocate(Sizes.Balance);
1910
1981
  writeBalance(value, 0, asset, amount);
1911
1982
  }
1912
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
+
1913
1993
  /// @notice Encode a CUSTODY block.
1914
1994
  /// @param host Host node ID holding the custody.
1915
1995
  /// @param asset Asset identifier.
1916
1996
  /// @param amount Token amount.
1917
1997
  /// @return value Encoded CUSTODY block bytes.
1918
- function custody(uint host, bytes32 asset, uint amount) internal pure returns (bytes memory value) {
1998
+ function createCustody(uint host, bytes32 asset, uint amount) internal pure returns (bytes memory value) {
1919
1999
  value = allocate(Sizes.B96);
1920
2000
  writeCustody(value, 0, host, asset, amount);
1921
2001
  }
@@ -1926,7 +2006,7 @@ library Blocks {
1926
2006
  /// @param liability Identifier for the liability side.
1927
2007
  /// @param debt Quantity owed on the liability side.
1928
2008
  /// @return value Encoded POSITION block bytes.
1929
- function position(
2009
+ function createPosition(
1930
2010
  bytes32 asset,
1931
2011
  uint amount,
1932
2012
  bytes32 liability,
@@ -1942,7 +2022,7 @@ library Blocks {
1942
2022
  /// @param asset Asset identifier.
1943
2023
  /// @param amount Transfer amount.
1944
2024
  /// @return value Encoded TRANSACTION block bytes.
1945
- function transaction(
2025
+ function createTransaction(
1946
2026
  bytes32 from,
1947
2027
  bytes32 to,
1948
2028
  bytes32 asset,
@@ -1959,14 +2039,14 @@ library Blocks {
1959
2039
  /// @param resources Packed resources assigned to the step.
1960
2040
  /// @param input Raw nested input payload.
1961
2041
  /// @return value Encoded STEP block bytes.
1962
- function step(uint cmd, uint resources, bytes memory input) internal pure returns (bytes memory value) {
2042
+ function createStep(uint cmd, uint resources, bytes memory input) internal pure returns (bytes memory value) {
1963
2043
  uint len = max32(Sizes.B64 + Sizes.Header + input.length);
1964
2044
  value = allocate(len);
1965
2045
  writeStep(value, 0, cmd, resources, input);
1966
2046
  }
1967
2047
 
1968
2048
  /// @notice Encode a STEP block by copying its nested input from calldata.
1969
- function stepCopy(uint cmd, uint resources, bytes calldata input) internal pure returns (bytes memory value) {
2049
+ function createStepCopy(uint cmd, uint resources, bytes calldata input) internal pure returns (bytes memory value) {
1970
2050
  uint len = max32(Sizes.B64 + Sizes.Header + input.length);
1971
2051
  value = allocate(len);
1972
2052
  copyStep(value, 0, cmd, resources, input);
@@ -1977,14 +2057,14 @@ library Blocks {
1977
2057
  /// @param resources Packed resources assigned to the call.
1978
2058
  /// @param payload Raw calldata payload for the target.
1979
2059
  /// @return value Encoded CALL block bytes.
1980
- function call(uint target, uint resources, bytes memory payload) internal pure returns (bytes memory value) {
2060
+ function createCall(uint target, uint resources, bytes memory payload) internal pure returns (bytes memory value) {
1981
2061
  uint len = max32(Sizes.B64 + Sizes.Header + payload.length);
1982
2062
  value = allocate(len);
1983
2063
  writeCall(value, 0, target, resources, payload);
1984
2064
  }
1985
2065
 
1986
2066
  /// @notice Encode a CALL block by copying its nested payload from calldata.
1987
- function callCopy(uint target, uint resources, bytes calldata payload) internal pure returns (bytes memory value) {
2067
+ function createCallCopy(uint target, uint resources, bytes calldata payload) internal pure returns (bytes memory value) {
1988
2068
  uint len = max32(Sizes.B64 + Sizes.Header + payload.length);
1989
2069
  value = allocate(len);
1990
2070
  copyCall(value, 0, target, resources, payload);
@@ -1996,14 +2076,14 @@ library Blocks {
1996
2076
  /// @param resources Chain-specific resources for the destination context.
1997
2077
  /// @param input Nested input block stream.
1998
2078
  /// @return value Encoded RELAY block bytes.
1999
- function relay(uint portal, uint resources, bytes memory input) internal pure returns (bytes memory value) {
2079
+ function createRelay(uint portal, uint resources, bytes memory input) internal pure returns (bytes memory value) {
2000
2080
  uint len = max32(Sizes.B64 + Sizes.Header + input.length);
2001
2081
  value = allocate(len);
2002
2082
  writeRelay(value, 0, portal, resources, input);
2003
2083
  }
2004
2084
 
2005
2085
  /// @notice Encode a RELAY block by copying its nested input from calldata.
2006
- function relayCopy(uint portal, uint resources, bytes calldata input) internal pure returns (bytes memory value) {
2086
+ function createRelayCopy(uint portal, uint resources, bytes calldata input) internal pure returns (bytes memory value) {
2007
2087
  uint len = max32(Sizes.B64 + Sizes.Header + input.length);
2008
2088
  value = allocate(len);
2009
2089
  copyRelay(value, 0, portal, resources, input);
@@ -2015,14 +2095,14 @@ library Blocks {
2015
2095
  /// @param resources Chain-specific resources for the destination dispatch.
2016
2096
  /// @param payload Encoded payload.
2017
2097
  /// @return value Encoded DISPATCH block bytes.
2018
- function dispatch(uint portal, uint resources, bytes memory payload) internal pure returns (bytes memory value) {
2098
+ function createDispatch(uint portal, uint resources, bytes memory payload) internal pure returns (bytes memory value) {
2019
2099
  uint len = max32(Sizes.B64 + Sizes.Header + payload.length);
2020
2100
  value = allocate(len);
2021
2101
  writeDispatch(value, 0, portal, resources, payload);
2022
2102
  }
2023
2103
 
2024
2104
  /// @notice Encode a DISPATCH block by copying its nested payload from calldata.
2025
- function dispatchCopy(
2105
+ function createDispatchCopy(
2026
2106
  uint portal,
2027
2107
  uint resources,
2028
2108
  bytes calldata payload
@@ -2033,7 +2113,7 @@ library Blocks {
2033
2113
  }
2034
2114
 
2035
2115
  /// @notice Encode a CONTEXT block.
2036
- function context(
2116
+ function createContext(
2037
2117
  bytes32 account,
2038
2118
  bytes memory state,
2039
2119
  bytes memory input
@@ -2044,7 +2124,7 @@ library Blocks {
2044
2124
  }
2045
2125
 
2046
2126
  /// @notice Encode a CONTEXT block by copying its nested streams from calldata.
2047
- function contextCopy(
2127
+ function createContextCopy(
2048
2128
  bytes32 account,
2049
2129
  bytes calldata state,
2050
2130
  bytes calldata input
@@ -2055,7 +2135,7 @@ library Blocks {
2055
2135
  }
2056
2136
 
2057
2137
  /// @notice Encode a RECOVER block.
2058
- function recover(
2138
+ function createRecover(
2059
2139
  uint handler,
2060
2140
  uint resources,
2061
2141
  bytes32 recoverykey,
@@ -2067,7 +2147,7 @@ library Blocks {
2067
2147
  }
2068
2148
 
2069
2149
  /// @notice Encode a RECOVER block by copying its nested witness from calldata.
2070
- function recoverCopy(
2150
+ function createRecoverCopy(
2071
2151
  uint handler,
2072
2152
  uint resources,
2073
2153
  bytes32 recoverykey,
@@ -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.
@@ -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 asset and liability sides; commands may transform either side
61
- // - position state is transient and does not itself create or erase an externally persisted obligation
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.
@@ -28,23 +28,20 @@ abstract contract Allocate is CommandBase, AllocateHook {
28
28
  }
29
29
 
30
30
  /// @notice Allocate BALANCE state blocks to matching NODE input blocks.
31
- /// @param state BALANCE block stream.
32
- /// @param input Matching NODE block stream.
31
+ /// @param context Command context carrying BALANCE state and matching NODE input.
33
32
  /// @return CUSTODY block stream matching the allocated balances.
34
33
  /// @return Empty transaction stream.
35
34
  function allocate(
36
- bytes32 account,
37
- bytes calldata state,
38
- bytes calldata input
35
+ bytes calldata context
39
36
  ) external onlyCommand returns (bytes memory, bytes memory) {
40
- Execution memory exec = openCommand(state, input, descriptor, 0);
37
+ Execution memory exec = openCommand(context, descriptor, 0);
41
38
 
42
39
  while (exec.more()) {
43
40
  HostAmount memory custody = exec.unpackBalanceForHost(Lanes.State, exec.unpackNode(Lanes.Input));
44
- allocate(account, custody);
41
+ allocate(exec.account, custody);
45
42
  exec.outputCustody(custody);
46
43
  }
47
44
 
48
- return close(exec, account);
45
+ return closeCommand(exec);
49
46
  }
50
47
  }
package/commands/Base.sol CHANGED
@@ -70,40 +70,56 @@ abstract contract CommandBase is CallerAccess, EndpointBase, ReceivedEvent {
70
70
  published = endpoint(id, name, descriptor);
71
71
  }
72
72
 
73
- /// @notice Open and validate both command lanes, including lanes declared EMPTY.
73
+ /// @notice Decode the command ABI argument as exactly one complete CONTEXT block.
74
+ /// @dev Rejects empty input, trailing bytes, and additional context blocks.
75
+ function unpackCommandContext(
76
+ bytes calldata context
77
+ ) internal pure returns (bytes32 account, bytes calldata state, bytes calldata input) {
78
+ uint abs;
79
+ assembly ("memory-safe") {
80
+ abs := context.offset
81
+ }
82
+
83
+ uint end;
84
+ (account, state, input, end) = Blocks.unpackContext(abs);
85
+ if (end != abs + context.length) revert Blocks.InvalidBlock();
86
+ }
87
+
88
+ /// @notice Decode one command context and validate both lanes, including lanes declared EMPTY.
74
89
  /// Batches are derived from the input and state lanes. A non-empty stream for
75
90
  /// a lane whose descriptor has zero stride reverts instead of being ignored.
76
91
  /// Commands must account for the complete validated state by consuming it,
77
92
  /// transforming and returning it, forwarding it intact, or reverting.
78
- /// @param state Current command state block stream.
79
- /// @param input Command input block stream.
93
+ /// @param context Exactly one CONTEXT block carrying the account, state, and input.
80
94
  /// @param descriptor Packed command endpoint descriptor.
81
95
  /// @param batches Required batch count, or zero to reconcile the lane counts.
82
96
  /// @return exec Execution with its output buffer metadata initialized for the reconciled batch count.
83
97
  function openCommand(
84
- bytes calldata state,
85
- bytes calldata input,
98
+ bytes calldata context,
86
99
  uint descriptor,
87
100
  uint batches
88
101
  ) internal view returns (Execution memory exec) {
89
- return Executions.open(state, input, descriptor, batches);
102
+ bytes32 account;
103
+ bytes calldata state;
104
+ bytes calldata input;
105
+ (account, state, input) = unpackCommandContext(context);
106
+ exec = Executions.open(state, input, descriptor, batches);
107
+ exec.account = account;
90
108
  }
91
109
 
92
- /// @notice Close a command execution and refund unspent value to `account`.
110
+ /// @notice Close a command execution and refund unspent value to its account.
93
111
  /// @param exec Command execution to close.
94
- /// @param account Account that should receive any unspent value.
95
112
  /// @return output Final encoded output block stream.
96
113
  /// @return transactions Final encoded transaction block stream.
97
- function close(
98
- Execution memory exec,
99
- bytes32 account
114
+ function closeCommand(
115
+ Execution memory exec
100
116
  ) internal returns (bytes memory output, bytes memory transactions) {
101
117
  if (exec.budget == 0 && Cursors.initial(exec.writers)) return ("", "");
102
118
 
103
119
  output = close(exec);
104
- uint amount = exec.refundValue(account, nativeAsset);
120
+ uint amount = exec.refundValue(exec.account, nativeAsset);
105
121
  if (amount != 0) {
106
- emit Received(account, nativeAsset, amount, Actions.Refund, 0);
122
+ emit Received(exec.account, nativeAsset, amount, Actions.Refund, 0);
107
123
  }
108
124
 
109
125
  transactions = exec.finishTransactions();
package/commands/Burn.sol CHANGED
@@ -30,22 +30,20 @@ abstract contract Burn is CommandBase, BurnHook, Action {
30
30
  }
31
31
 
32
32
  /// @notice Burn each BALANCE block from the command state.
33
- /// @param state BALANCE block stream.
33
+ /// @param context Command context carrying the BALANCE state stream.
34
34
  /// @return Empty output state.
35
35
  /// @return Empty transaction stream.
36
36
  function burn(
37
- bytes32 account,
38
- bytes calldata state,
39
- bytes calldata input
37
+ bytes calldata context
40
38
  ) external onlyCommand returns (bytes memory, bytes memory) {
41
- Execution memory exec = openCommand(state, input, descriptor, 0);
39
+ Execution memory exec = openCommand(context, descriptor, 0);
42
40
 
43
41
  while (exec.more()) {
44
42
  (bytes32 asset, uint amount) = exec.unpackBalance(Lanes.State);
45
- burn(account, asset, amount);
43
+ burn(exec.account, asset, amount);
46
44
  }
47
45
 
48
- return close(exec, account);
46
+ return closeCommand(exec);
49
47
  }
50
48
  }
51
49