@rootzero/contracts 0.5.1 → 0.6.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 (44) hide show
  1. package/Commands.sol +7 -5
  2. package/Utils.sol +2 -2
  3. package/commands/Base.sol +28 -0
  4. package/commands/Borrow.sol +5 -4
  5. package/commands/Burn.sol +3 -2
  6. package/commands/Create.sol +3 -2
  7. package/commands/Credit.sol +3 -2
  8. package/commands/Debit.sol +3 -2
  9. package/commands/Deposit.sol +52 -5
  10. package/commands/Liquidate.sol +5 -4
  11. package/commands/Liquidity.sol +9 -8
  12. package/commands/Mint.sol +3 -2
  13. package/commands/Pipe.sol +17 -20
  14. package/commands/Provision.sol +64 -23
  15. package/commands/Reclaim.sol +3 -2
  16. package/commands/Redeem.sol +5 -4
  17. package/commands/Remove.sol +3 -2
  18. package/commands/Repay.sol +5 -4
  19. package/commands/Settle.sol +3 -2
  20. package/commands/Stake.sol +7 -6
  21. package/commands/Supply.sol +3 -2
  22. package/commands/Swap.sol +5 -4
  23. package/commands/Transfer.sol +3 -2
  24. package/commands/Unstake.sol +3 -2
  25. package/commands/Withdraw.sol +3 -2
  26. package/commands/admin/Allocate.sol +3 -2
  27. package/commands/admin/AllowAssets.sol +3 -2
  28. package/commands/admin/Authorize.sol +3 -2
  29. package/commands/admin/DenyAssets.sol +3 -2
  30. package/commands/admin/Destroy.sol +3 -2
  31. package/commands/admin/Init.sol +3 -2
  32. package/commands/admin/Relocate.sol +13 -9
  33. package/commands/admin/Unauthorize.sol +3 -2
  34. package/core/Host.sol +3 -3
  35. package/events/Command.sol +12 -5
  36. package/events/Peer.sol +4 -2
  37. package/package.json +1 -1
  38. package/peer/AllowAssets.sol +2 -2
  39. package/peer/DenyAssets.sol +2 -2
  40. package/peer/Pull.sol +2 -2
  41. package/peer/Push.sol +2 -2
  42. package/peer/Settle.sol +2 -2
  43. package/utils/Utils.sol +8 -0
  44. package/utils/Value.sol +15 -6
@@ -1,34 +1,37 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
- import { CommandBase, CommandContext, State } from "../Base.sol";
4
+ import { CommandContext, CommandPayable, State } from "../Base.sol";
5
5
  import { Cursors, Cur, Schemas } from "../../Cursors.sol";
6
+ import { Budget, Values } from "../../utils/Value.sol";
6
7
  using Cursors for Cur;
7
8
 
8
- string constant NAME = "relocate";
9
+ string constant NAME = "relocatePayable";
9
10
 
10
- /// @title Relocate
11
+ /// @title RelocatePayable
11
12
  /// @notice Admin command that forwards native value (ETH) to one or more destination hosts.
12
13
  /// Each FUNDING block in the request specifies a target host node ID and an amount to forward.
13
14
  /// Only callable by the admin account.
14
- abstract contract Relocate is CommandBase {
15
- uint internal immutable relocateId = commandId(NAME);
15
+ abstract contract RelocatePayable is CommandPayable {
16
+ uint internal immutable relocatePayableId = commandId(NAME);
16
17
 
17
18
  constructor() {
18
- emit Command(host, NAME, Schemas.Funding, relocateId, State.Empty, State.Empty);
19
+ emit Command(host, NAME, Schemas.Funding, relocatePayableId, State.Empty, State.Empty, true);
19
20
  }
20
21
 
21
- function relocate(
22
+ function relocatePayable(
22
23
  CommandContext calldata c
23
- ) external payable onlyAdmin(c.account) onlyCommand(relocateId, c.target) returns (bytes memory) {
24
+ ) external payable onlyAdmin(c.account) onlyCommand(relocatePayableId, c.target) returns (bytes memory) {
24
25
  (Cur memory request, , ) = cursor(c.request, 1);
26
+ Budget memory budget = Values.fromMsg();
25
27
 
26
28
  while (request.i < request.bound) {
27
29
  (uint host, uint amount) = request.unpackFunding();
28
- callTo(host, amount, "");
30
+ callTo(host, Values.use(budget, amount), "");
29
31
  }
30
32
 
31
33
  request.complete();
34
+ settleValue(c.account, budget);
32
35
  return "";
33
36
  }
34
37
  }
@@ -37,3 +40,4 @@ abstract contract Relocate is CommandBase {
37
40
 
38
41
 
39
42
 
43
+
@@ -15,12 +15,12 @@ abstract contract Unauthorize is CommandBase {
15
15
  uint internal immutable unauthorizeId = commandId(NAME);
16
16
 
17
17
  constructor() {
18
- emit Command(host, NAME, Schemas.Node, unauthorizeId, State.Empty, State.Empty);
18
+ emit Command(host, NAME, Schemas.Node, unauthorizeId, State.Empty, State.Empty, false);
19
19
  }
20
20
 
21
21
  function unauthorize(
22
22
  CommandContext calldata c
23
- ) external payable onlyAdmin(c.account) onlyCommand(unauthorizeId, c.target) returns (bytes memory) {
23
+ ) external onlyAdmin(c.account) onlyCommand(unauthorizeId, c.target) returns (bytes memory) {
24
24
  (Cur memory request, , ) = cursor(c.request, 1);
25
25
 
26
26
  while (request.i < request.bound) {
@@ -36,3 +36,4 @@ abstract contract Unauthorize is CommandBase {
36
36
 
37
37
 
38
38
 
39
+
package/core/Host.sol CHANGED
@@ -4,7 +4,7 @@ pragma solidity ^0.8.33;
4
4
  import { AccessControl } from "./Access.sol";
5
5
  import { Authorize } from "../commands/admin/Authorize.sol";
6
6
  import { Unauthorize } from "../commands/admin/Unauthorize.sol";
7
- import { Relocate } from "../commands/admin/Relocate.sol";
7
+ import { RelocatePayable } from "../commands/admin/Relocate.sol";
8
8
  import { HostAnnouncedEvent } from "../events/HostAnnounced.sol";
9
9
  import { IHostDiscovery } from "../interfaces/IHostDiscovery.sol";
10
10
  import { Ids } from "../utils/Ids.sol";
@@ -25,10 +25,10 @@ abstract contract HostDiscovery is HostAnnouncedEvent, IHostDiscovery {
25
25
 
26
26
  /// @title Host
27
27
  /// @notice Abstract base contract for rootzero host implementations.
28
- /// Inherits admin command support (authorize, unauthorize, relocate) and
28
+ /// Inherits admin command support (authorize, unauthorize, relocatePayable) and
29
29
  /// optionally announces itself to a discovery contract at deployment.
30
30
  /// Accepts native ETH payments via the `receive` function.
31
- abstract contract Host is Authorize, Unauthorize, Relocate {
31
+ abstract contract Host is Authorize, Unauthorize, RelocatePayable {
32
32
  /// @param cmdr Commander address; passed to `AccessControl`.
33
33
  /// If `cmdr` is a deployed contract, the host calls `announceHost`
34
34
  /// on it during construction to register with the discovery registry.
@@ -3,7 +3,8 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import { EventEmitter } from "./Emitter.sol";
5
5
 
6
- string constant ABI = "event Command(uint indexed host, string name, string schema, uint cid, uint8 stateIn, uint8 stateOut)";
6
+ string constant ABI =
7
+ "event Command(uint indexed host, string name, string schema, uint cid, uint8 stateIn, uint8 stateOut, bool acceptsValue)";
7
8
 
8
9
  /// @notice Emitted once per command during host deployment to publish its schema and state types.
9
10
  abstract contract CommandEvent is EventEmitter {
@@ -13,12 +14,18 @@ abstract contract CommandEvent is EventEmitter {
13
14
  /// @param cid Command node ID.
14
15
  /// @param stateIn State type discriminant for the input state (see `State` library).
15
16
  /// @param stateOut State type discriminant for the output state.
16
- event Command(uint indexed host, string name, string schema, uint cid, uint8 stateIn, uint8 stateOut);
17
+ /// @param acceptsValue Whether the command entrypoint accepts nonzero `msg.value`.
18
+ event Command(
19
+ uint indexed host,
20
+ string name,
21
+ string schema,
22
+ uint cid,
23
+ uint8 stateIn,
24
+ uint8 stateOut,
25
+ bool acceptsValue
26
+ );
17
27
 
18
28
  constructor() {
19
29
  emit EventAbi(ABI);
20
30
  }
21
31
  }
22
-
23
-
24
-
package/events/Peer.sol CHANGED
@@ -3,7 +3,8 @@ pragma solidity ^0.8.33;
3
3
 
4
4
  import { EventEmitter } from "./Emitter.sol";
5
5
 
6
- string constant ABI = "event Peer(uint indexed host, string name, string schema, uint pid)";
6
+ string constant ABI =
7
+ "event Peer(uint indexed host, string name, string schema, uint pid, bool acceptsValue)";
7
8
 
8
9
  /// @notice Emitted once per peer during host deployment to publish its schema.
9
10
  abstract contract PeerEvent is EventEmitter {
@@ -11,7 +12,8 @@ abstract contract PeerEvent is EventEmitter {
11
12
  /// @param name Human-readable peer name.
12
13
  /// @param schema Schema DSL string describing the peer request shape.
13
14
  /// @param pid Peer node ID.
14
- event Peer(uint indexed host, string name, string schema, uint pid);
15
+ /// @param acceptsValue Whether the peer entrypoint accepts nonzero `msg.value`.
16
+ event Peer(uint indexed host, string name, string schema, uint pid, bool acceptsValue);
15
17
 
16
18
  constructor() {
17
19
  emit EventAbi(ABI);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rootzero/contracts",
3
- "version": "0.5.1",
3
+ "version": "0.6.0",
4
4
  "description": "Solidity contracts and protocol building blocks for rootzero hosts and commands.",
5
5
  "private": false,
6
6
  "license": "GPL-3.0-only",
@@ -15,7 +15,7 @@ abstract contract PeerAllowAssets is PeerBase {
15
15
  uint internal immutable peerAllowAssetsId = peerId(NAME);
16
16
 
17
17
  constructor() {
18
- emit Peer(host, NAME, Schemas.Asset, peerAllowAssetsId);
18
+ emit Peer(host, NAME, Schemas.Asset, peerAllowAssetsId, false);
19
19
  }
20
20
 
21
21
  /// @notice Override to permit a single (asset, meta) pair.
@@ -25,7 +25,7 @@ abstract contract PeerAllowAssets is PeerBase {
25
25
  function peerAllowAsset(bytes32 asset, bytes32 meta) internal virtual returns (bool);
26
26
 
27
27
  /// @notice Execute the allow-assets peer call.
28
- function peerAllowAssets(bytes calldata request) external payable onlyPeer returns (bytes memory) {
28
+ function peerAllowAssets(bytes calldata request) external onlyPeer returns (bytes memory) {
29
29
  (Cur memory assets, , ) = cursor(request, 1);
30
30
 
31
31
  while (assets.i < assets.bound) {
@@ -15,7 +15,7 @@ abstract contract PeerDenyAssets is PeerBase {
15
15
  uint internal immutable peerDenyAssetsId = peerId(NAME);
16
16
 
17
17
  constructor() {
18
- emit Peer(host, NAME, Schemas.Asset, peerDenyAssetsId);
18
+ emit Peer(host, NAME, Schemas.Asset, peerDenyAssetsId, false);
19
19
  }
20
20
 
21
21
  /// @notice Override to block a single (asset, meta) pair.
@@ -25,7 +25,7 @@ abstract contract PeerDenyAssets is PeerBase {
25
25
  function peerDenyAsset(bytes32 asset, bytes32 meta) internal virtual returns (bool);
26
26
 
27
27
  /// @notice Execute the deny-assets peer call.
28
- function peerDenyAssets(bytes calldata request) external payable onlyPeer returns (bytes memory) {
28
+ function peerDenyAssets(bytes calldata request) external onlyPeer returns (bytes memory) {
29
29
  (Cur memory assets, , ) = cursor(request, 1);
30
30
 
31
31
  while (assets.i < assets.bound) {
package/peer/Pull.sol CHANGED
@@ -15,7 +15,7 @@ abstract contract PeerPull is PeerBase {
15
15
  uint internal immutable peerPullId = peerId(NAME);
16
16
 
17
17
  constructor(string memory input) {
18
- emit Peer(host, NAME, input, peerPullId);
18
+ emit Peer(host, NAME, input, peerPullId, false);
19
19
  }
20
20
 
21
21
  /// @notice Override to process a single incoming block from the pull request.
@@ -23,7 +23,7 @@ abstract contract PeerPull is PeerBase {
23
23
  function peerPull(Cur memory input) internal virtual;
24
24
 
25
25
  /// @notice Execute the pull peer call.
26
- function peerPull(bytes calldata request) external payable onlyPeer returns (bytes memory) {
26
+ function peerPull(bytes calldata request) external onlyPeer returns (bytes memory) {
27
27
  (Cur memory input, , ) = cursor(request, 1);
28
28
 
29
29
  while (input.i < input.bound) {
package/peer/Push.sol CHANGED
@@ -15,7 +15,7 @@ abstract contract PeerPush is PeerBase {
15
15
  uint internal immutable peerPushId = peerId(NAME);
16
16
 
17
17
  constructor(string memory input) {
18
- emit Peer(host, NAME, input, peerPushId);
18
+ emit Peer(host, NAME, input, peerPushId, false);
19
19
  }
20
20
 
21
21
  /// @notice Override to process a single incoming block from the push request.
@@ -23,7 +23,7 @@ abstract contract PeerPush is PeerBase {
23
23
  function peerPush(Cur memory input) internal virtual;
24
24
 
25
25
  /// @notice Execute the push peer call.
26
- function peerPush(bytes calldata request) external payable onlyPeer returns (bytes memory) {
26
+ function peerPush(bytes calldata request) external onlyPeer returns (bytes memory) {
27
27
  (Cur memory input, , ) = cursor(request, 1);
28
28
 
29
29
  while (input.i < input.bound) {
package/peer/Settle.sol CHANGED
@@ -16,11 +16,11 @@ abstract contract PeerSettle is PeerBase, TransferHook {
16
16
  uint internal immutable peerSettleId = peerId(NAME);
17
17
 
18
18
  constructor() {
19
- emit Peer(host, NAME, Schemas.Transaction, peerSettleId);
19
+ emit Peer(host, NAME, Schemas.Transaction, peerSettleId, false);
20
20
  }
21
21
 
22
22
  /// @notice Execute the peer-settle call.
23
- function peerSettle(bytes calldata request) external payable onlyPeer returns (bytes memory) {
23
+ function peerSettle(bytes calldata request) external onlyPeer returns (bytes memory) {
24
24
  (Cur memory state, , ) = cursor(request, 1);
25
25
 
26
26
  while (state.i < state.bound) {
package/utils/Utils.sol CHANGED
@@ -116,6 +116,14 @@ function hash32(bytes32 value) pure returns (bytes32 hash) {
116
116
  }
117
117
  }
118
118
 
119
+ /// @notice Build a retry ticket commitment for an account and state payload.
120
+ /// @param account Account identifier associated with the retryable payload.
121
+ /// @param state Serialized state bytes for the retryable payload.
122
+ /// @return ticket Keccak256 hash of `account` and `state`.
123
+ function retryTicket(bytes32 account, bytes calldata state) pure returns (bytes32 ticket) {
124
+ return keccak256(abi.encode(account, state));
125
+ }
126
+
119
127
  /// @notice Build the chain-local base prefix for a 256-bit ID.
120
128
  /// Embeds the current `block.chainid` so IDs are not portable across chains.
121
129
  /// @param prefix Four-byte type tag (e.g. `Ids.Host`, `Ids.Command`).
package/utils/Value.sol CHANGED
@@ -1,18 +1,18 @@
1
1
  // SPDX-License-Identifier: GPL-3.0-only
2
2
  pragma solidity ^0.8.33;
3
3
 
4
+ /// @notice Mutable native-value budget drawn down as sub-calls consume ETH.
5
+ struct Budget {
6
+ /// @dev Remaining unspent native value in wei.
7
+ uint remaining;
8
+ }
9
+
4
10
  /// @title Values
5
11
  /// @notice Native-value (ETH) budget tracking for commands that accept `msg.value`.
6
12
  library Values {
7
13
  /// @dev Thrown when a call attempts to spend more native value than remains in the budget.
8
14
  error InsufficientValue();
9
15
 
10
- /// @notice Mutable native-value budget drawn down as sub-calls consume ETH.
11
- struct Budget {
12
- /// @dev Remaining unspent native value in wei.
13
- uint remaining;
14
- }
15
-
16
16
  /// @notice Create a budget from the current call's `msg.value`.
17
17
  /// @return Budget initialised with the full `msg.value`.
18
18
  function fromMsg() internal view returns (Budget memory) {
@@ -29,4 +29,13 @@ library Values {
29
29
  budget.remaining -= amount;
30
30
  return amount;
31
31
  }
32
+
33
+ /// @notice Deduct all remaining native value from the budget and return it.
34
+ /// @param budget Mutable budget to drain.
35
+ /// @return Remaining native value before the budget was emptied.
36
+ function drain(Budget memory budget) internal pure returns (uint) {
37
+ uint amount = budget.remaining;
38
+ budget.remaining = 0;
39
+ return amount;
40
+ }
32
41
  }