@rootzero/contracts 0.4.0 → 0.5.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 (96) hide show
  1. package/{Cursors.sol → contracts/Cursors.sol} +1 -2
  2. package/{blocks → contracts/blocks}/Cursors.sol +18 -0
  3. package/{blocks → contracts/blocks}/Keys.sol +1 -1
  4. package/{blocks → contracts/blocks}/Schema.sol +1 -1
  5. package/{blocks → contracts/blocks}/Writers.sol +2 -2
  6. package/{commands → contracts/commands}/Provision.sol +1 -3
  7. package/{commands → contracts/commands}/Settle.sol +4 -8
  8. package/{commands → contracts/commands}/Transfer.sol +18 -11
  9. package/{events → contracts/events}/RootZero.sol +2 -3
  10. package/contracts/peer/Settle.sol +34 -0
  11. package/contracts/test/TestBorrowHost.sol +72 -0
  12. package/contracts/test/TestBurnHost.sol +31 -0
  13. package/contracts/test/TestCreateHost.sol +40 -0
  14. package/contracts/test/TestCursorHelper.sol +191 -0
  15. package/contracts/test/TestDiscovery.sol +9 -0
  16. package/contracts/test/TestECDSA.sol +19 -0
  17. package/contracts/test/TestHost.sol +218 -0
  18. package/contracts/test/TestLiquidityHost.sol +167 -0
  19. package/contracts/test/TestMintHost.sol +50 -0
  20. package/contracts/test/TestOperation.sol +21 -0
  21. package/contracts/test/TestPeerHost.sol +57 -0
  22. package/contracts/test/TestReclaimHost.sol +55 -0
  23. package/contracts/test/TestRejectEther.sol +11 -0
  24. package/contracts/test/TestRemoveHost.sol +40 -0
  25. package/contracts/test/TestSupplyHost.sol +25 -0
  26. package/contracts/test/TestSwapHost.sol +67 -0
  27. package/contracts/test/TestUtils.sol +184 -0
  28. package/contracts/test/TestValidator.sol +13 -0
  29. package/{utils → contracts/utils}/Accounts.sol +11 -0
  30. package/package.json +33 -17
  31. package/blocks/Mem.sol +0 -188
  32. package/docs/GETTING_STARTED.md +0 -286
  33. /package/{Commands.sol → contracts/Commands.sol} +0 -0
  34. /package/{Core.sol → contracts/Core.sol} +0 -0
  35. /package/{Events.sol → contracts/Events.sol} +0 -0
  36. /package/{Utils.sol → contracts/Utils.sol} +0 -0
  37. /package/{commands → contracts/commands}/Base.sol +0 -0
  38. /package/{commands → contracts/commands}/Borrow.sol +0 -0
  39. /package/{commands → contracts/commands}/Burn.sol +0 -0
  40. /package/{commands → contracts/commands}/Create.sol +0 -0
  41. /package/{commands → contracts/commands}/Credit.sol +0 -0
  42. /package/{commands → contracts/commands}/Debit.sol +0 -0
  43. /package/{commands → contracts/commands}/Deposit.sol +0 -0
  44. /package/{commands → contracts/commands}/Liquidate.sol +0 -0
  45. /package/{commands → contracts/commands}/Liquidity.sol +0 -0
  46. /package/{commands → contracts/commands}/Mint.sol +0 -0
  47. /package/{commands → contracts/commands}/Pipe.sol +0 -0
  48. /package/{commands → contracts/commands}/Reclaim.sol +0 -0
  49. /package/{commands → contracts/commands}/Redeem.sol +0 -0
  50. /package/{commands → contracts/commands}/Remove.sol +0 -0
  51. /package/{commands → contracts/commands}/Repay.sol +0 -0
  52. /package/{commands → contracts/commands}/Stake.sol +0 -0
  53. /package/{commands → contracts/commands}/Supply.sol +0 -0
  54. /package/{commands → contracts/commands}/Swap.sol +0 -0
  55. /package/{commands → contracts/commands}/Unstake.sol +0 -0
  56. /package/{commands → contracts/commands}/Withdraw.sol +0 -0
  57. /package/{commands → contracts/commands}/admin/Allocate.sol +0 -0
  58. /package/{commands → contracts/commands}/admin/AllowAssets.sol +0 -0
  59. /package/{commands → contracts/commands}/admin/Authorize.sol +0 -0
  60. /package/{commands → contracts/commands}/admin/DenyAssets.sol +0 -0
  61. /package/{commands → contracts/commands}/admin/Destroy.sol +0 -0
  62. /package/{commands → contracts/commands}/admin/Init.sol +0 -0
  63. /package/{commands → contracts/commands}/admin/Relocate.sol +0 -0
  64. /package/{commands → contracts/commands}/admin/Unauthorize.sol +0 -0
  65. /package/{core → contracts/core}/Access.sol +0 -0
  66. /package/{core → contracts/core}/Balances.sol +0 -0
  67. /package/{core → contracts/core}/Host.sol +0 -0
  68. /package/{core → contracts/core}/Operation.sol +0 -0
  69. /package/{core → contracts/core}/Validator.sol +0 -0
  70. /package/{events → contracts/events}/Access.sol +0 -0
  71. /package/{events → contracts/events}/Asset.sol +0 -0
  72. /package/{events → contracts/events}/Balance.sol +0 -0
  73. /package/{events → contracts/events}/Collateral.sol +0 -0
  74. /package/{events → contracts/events}/Command.sol +0 -0
  75. /package/{events → contracts/events}/Debt.sol +0 -0
  76. /package/{events → contracts/events}/Deposit.sol +0 -0
  77. /package/{events → contracts/events}/Emitter.sol +0 -0
  78. /package/{events → contracts/events}/Governed.sol +0 -0
  79. /package/{events → contracts/events}/HostAnnounced.sol +0 -0
  80. /package/{events → contracts/events}/Listing.sol +0 -0
  81. /package/{events → contracts/events}/Peer.sol +0 -0
  82. /package/{events → contracts/events}/Quote.sol +0 -0
  83. /package/{events → contracts/events}/Withdraw.sol +0 -0
  84. /package/{interfaces → contracts/interfaces}/IHostDiscovery.sol +0 -0
  85. /package/{peer → contracts/peer}/AllowAssets.sol +0 -0
  86. /package/{peer → contracts/peer}/Base.sol +0 -0
  87. /package/{peer → contracts/peer}/DenyAssets.sol +0 -0
  88. /package/{peer → contracts/peer}/Pull.sol +0 -0
  89. /package/{peer → contracts/peer}/Push.sol +0 -0
  90. /package/{utils → contracts/utils}/Assets.sol +0 -0
  91. /package/{utils → contracts/utils}/ECDSA.sol +0 -0
  92. /package/{utils → contracts/utils}/Ids.sol +0 -0
  93. /package/{utils → contracts/utils}/Layout.sol +0 -0
  94. /package/{utils → contracts/utils}/State.sol +0 -0
  95. /package/{utils → contracts/utils}/Utils.sol +0 -0
  96. /package/{utils → contracts/utils}/Value.sol +0 -0
@@ -1,286 +0,0 @@
1
- # Getting Started With rootzero
2
-
3
- This guide is for developers who want to build on rootzero without reading the whole codebase first.
4
-
5
- If you remember only one thing, remember this:
6
-
7
- - A `Host` is your application contract.
8
- - A command is an entrypoint the rootzero runtime is allowed to call.
9
- - Requests and responses are passed around as typed byte blocks.
10
-
11
- ## The Mental Model
12
-
13
- rootzero moves data through a small command context:
14
-
15
- ```solidity
16
- struct CommandContext {
17
- uint target;
18
- bytes32 account;
19
- bytes state;
20
- bytes request;
21
- }
22
- ```
23
-
24
- In practice:
25
-
26
- - `account` is the user account the command is acting for.
27
- - `request` is the new input for this command.
28
- - `state` is data produced by an earlier command in a pipeline.
29
- - `target` is the command id you expect to receive, or `0`.
30
-
31
- Most built-in commands follow a simple pattern:
32
-
33
- - read blocks from `request` or `state`
34
- - apply your host logic
35
- - return new blocks
36
-
37
- ## Step 1: Start With A Host
38
-
39
- The smallest useful rootzero app is a host contract.
40
-
41
- ```solidity
42
- // SPDX-License-Identifier: MIT
43
- pragma solidity ^0.8.33;
44
-
45
- import {Host} from "@rootzero/contracts/Core.sol";
46
-
47
- contract ExampleHost is Host {
48
- constructor(address rootzero)
49
- Host(rootzero, 1, "example")
50
- {}
51
- }
52
- ```
53
-
54
- What the constructor arguments mean:
55
-
56
- - `rootzero`: the trusted rootzero runtime allowed to call commands
57
- - `1`: your host version
58
- - `"example"`: your host namespace
59
-
60
- If `rootzero` is a contract, the host announces itself there during deployment. If you pass `address(0)`, the host becomes self-managed and does not auto-register.
61
-
62
- ## Step 2: Reuse A Built-In Command
63
-
64
- The easiest way to integrate is to inherit a built-in command module and implement its hook.
65
-
66
- This example adds `DebitAccount`, which turns `AMOUNT` blocks in `request` into `BALANCE` blocks in the response:
67
-
68
- ```solidity
69
- // SPDX-License-Identifier: MIT
70
- pragma solidity ^0.8.33;
71
-
72
- import {Host} from "@rootzero/contracts/Core.sol";
73
- import {DebitAccount} from "@rootzero/contracts/Commands.sol";
74
- import {Assets} from "@rootzero/contracts/Utils.sol";
75
-
76
- contract ExampleHost is Host, DebitAccount {
77
- mapping(bytes32 account => mapping(bytes32 assetKey => uint amount)) internal balances;
78
-
79
- constructor(address rootzero)
80
- Host(rootzero, 1, "example")
81
- {}
82
-
83
- function debitAccount(
84
- bytes32 account,
85
- bytes32 asset,
86
- bytes32 meta,
87
- uint amount
88
- ) internal override {
89
- bytes32 key = Assets.key(asset, meta);
90
- balances[account][key] -= amount;
91
- }
92
- }
93
- ```
94
-
95
- Why this is a good first step:
96
-
97
- - you do not need to write block parsing yourself
98
- - you get the standard rootzero command surface
99
- - you only implement the business rule that is unique to your app
100
-
101
- ## Step 3: Understand What Built-In Commands Consume
102
-
103
- The built-in commands are easiest to use when you know which blocks they expect.
104
-
105
- ### Commands That Read `request`
106
-
107
- - `deposit`: reads `AMOUNT` blocks, returns `BALANCE`
108
- - `transfer`: reads `AMOUNT` plus `RECIPIENT`
109
- - `debitAccount`: reads `AMOUNT`, returns `BALANCE`
110
- - `provision`: reads `AMOUNT` plus `NODE`, returns `CUSTODY`
111
- - `pipe`: reads `STEP` blocks and runs them in order
112
-
113
- ### Commands That Read `state`
114
-
115
- - `withdraw`: reads `BALANCE`, optionally reads `RECIPIENT` from `request`
116
- - `creditAccount`: reads `BALANCE`, optionally reads `RECIPIENT` from `request`
117
- - `settle`: reads `TX`
118
- - `provisionFromBalance`: reads `BALANCE` from `state` and `NODE` from `request`
119
-
120
- This is the main pattern to keep in mind:
121
-
122
- - use `request` for the command's direct input
123
- - use `state` when a previous command already produced the input
124
-
125
- ## Step 4: Send A Simple Request
126
-
127
- For a host that supports `deposit`, a request with one `AMOUNT` block is enough.
128
-
129
- TypeScript helper example:
130
-
131
- ```ts
132
- import { ethers } from "ethers";
133
- import { encodeAmountBlock } from "../test/helpers/blocks.js";
134
-
135
- const asset = ethers.zeroPadValue("0x01", 32);
136
- const meta = ethers.ZeroHash;
137
- const amount = 100n;
138
-
139
- const ctx = {
140
- target: 0n,
141
- account: "0x...", // 32-byte rootzero account id
142
- state: "0x",
143
- request: encodeAmountBlock(asset, meta, amount),
144
- };
145
-
146
- await host.deposit(ctx);
147
- ```
148
-
149
- What happens:
150
-
151
- 1. `deposit` reads the `AMOUNT` block from `ctx.request`.
152
- 2. Your host applies its deposit logic.
153
- 3. The command returns one `BALANCE` block for each deposited amount.
154
-
155
- ## Step 5: Create A Custom Command
156
-
157
- When the built-in modules are not enough, add your own command entrypoint.
158
-
159
- ```solidity
160
- // SPDX-License-Identifier: MIT
161
- pragma solidity ^0.8.33;
162
-
163
- import {Host} from "@rootzero/contracts/Core.sol";
164
- import {CommandBase, CommandContext, Channels} from "@rootzero/contracts/Commands.sol";
165
- import {Cursors, Cursor, Schemas} from "@rootzero/contracts/Cursors.sol";
166
-
167
- using Cursors for Cursor;
168
-
169
- string constant NAME = "myCommand";
170
- string constant ROUTE = "route(uint foo, uint bar)";
171
- string constant INPUT = string.concat(ROUTE, "&", Schemas.Amount);
172
-
173
- abstract contract MyCommand is CommandBase {
174
- uint internal immutable myCommandId = commandId(NAME);
175
-
176
- constructor() {
177
- emit Command(host, NAME, INPUT, myCommandId, Channels.Setup, Channels.Balances);
178
- }
179
-
180
- function myCommand(
181
- CommandContext calldata c
182
- ) external payable onlyCommand(myCommandId, c.target) returns (bytes memory) {
183
- Cursor memory input = Cursors.openBlock(c.request, 0);
184
- uint foo = input.unpackRouteUint();
185
- (bytes32 asset, bytes32 meta, uint amount) = input.unpackAmount();
186
- foo;
187
- return Cursors.toBalanceBlock(asset, meta, amount);
188
- }
189
- }
190
- ```
191
-
192
- There are three important ideas here:
193
-
194
- - every custom command gets a deterministic command id
195
- - you announce it with the `Command` event
196
- - `onlyCommand(myCommandId, c.target)` ensures the trusted caller hit the right endpoint
197
-
198
- ## Step 6: Read Input With A Cursor
199
-
200
- Cursor parsing is the nicest way to read structured command input.
201
-
202
- If your request contains a bundled input like:
203
-
204
- - `route(uint foo) & amount(bytes32 asset, bytes32 meta, uint amount)`
205
-
206
- your command can:
207
-
208
- - open it with `Cursors.openBlock(...)`
209
- - consume the route first
210
- - then consume the amount
211
- - keep parsing in bundle/member order without indexing helpers
212
-
213
- For simple projects, it is perfectly fine to:
214
-
215
- - publish the full input schema string in the `Command` event
216
- - encode bundled input blocks off-chain
217
- - decode them sequentially with cursor helpers inside the command
218
-
219
- ## Step 7: Return State With Writers
220
-
221
- When your command needs to build response blocks manually, use `Writers`.
222
-
223
- ```solidity
224
- // SPDX-License-Identifier: MIT
225
- pragma solidity ^0.8.33;
226
-
227
- import {Writers, Writer} from "@rootzero/contracts/Cursors.sol";
228
-
229
- using Writers for Writer;
230
-
231
- function buildBalances() internal pure returns (bytes memory) {
232
- Writer memory writer = Writers.allocBalances(2);
233
- writer.appendBalance(bytes32(uint256(1)), bytes32(0), 50);
234
- writer.appendBalance(bytes32(uint256(2)), bytes32(0), 75);
235
- return writer.done();
236
- }
237
- ```
238
-
239
- Use this when your command needs to return:
240
-
241
- - balances
242
- - custodies
243
- - transactions
244
-
245
- If you are only consuming built-in commands, you often will not need to touch writers directly.
246
-
247
- ## A Tiny End-To-End Example
248
-
249
- Imagine you want a host that keeps internal balances and lets rootzero debit them.
250
-
251
- 1. Deploy a host that inherits `Host` and `DebitAccount`.
252
- 2. Store balances in your own mapping.
253
- 3. Implement `debitAccount(account, asset, meta, amount)`.
254
- 4. Send `debitAccountToBalance` a request containing one or more `AMOUNT` blocks.
255
- 5. rootzero returns `BALANCE` blocks representing the debited amounts.
256
-
257
- That is already a valid and useful integration.
258
-
259
- ## Which Files To Open Next
260
-
261
- If you want to learn by example, these are the best files to read next:
262
-
263
- - `examples/1-Host.sol`: smallest host
264
- - `examples/2-Basic.sol`: host plus a built-in command hook
265
- - `examples/3-Command.sol`: custom command id and command event
266
- - `examples/4-Batch.sol`: batching request input and building balance output
267
- - `examples/5-Route.sol`: bundled route input plus protocol blocks
268
- - `test/commands.test.ts`: concrete request and response examples
269
- - `test/helpers/blocks.ts`: block encoders you can reuse in off-chain tooling
270
-
271
- ## Common Mistakes
272
-
273
- - Passing data in `state` when the command expects it in `request`
274
- - Forgetting to emit a `Command` event for a custom command
275
- - Using the wrong `target` value for `onlyCommand`
276
- - Trying to parse raw bytes manually when a built-in reader already exists
277
- - Starting with a custom command when a built-in module already matches the job
278
-
279
- ## Recommended Learning Order
280
-
281
- 1. Deploy a plain `Host`.
282
- 2. Add one built-in command such as `DebitAccount` or `Deposit`.
283
- 3. Use the TypeScript block helpers to build requests.
284
- 4. Only then add a custom command with bundled input and cursor parsing.
285
-
286
- That path keeps the first integration small and easy to debug.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes