@rootzero/contracts 1.21.0 → 1.23.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 +125 -0
- package/Endpoints.sol +2 -3
- package/Events.sol +1 -1
- package/README.md +25 -19
- package/annotations/Action.sol +1 -1
- package/annotations/Label.sol +1 -1
- package/annotations/Schema.sol +36 -3
- package/codec/Blocks.sol +100 -29
- package/codec/Decoders.sol +62 -8
- package/codec/Readers.sol +39 -0
- package/codec/Schema.sol +44 -35
- package/codec/Writers.sol +8 -0
- package/commands/Allocate.sol +5 -8
- package/commands/Base.sol +29 -13
- package/commands/Burn.sol +5 -7
- package/commands/Credit.sol +5 -7
- package/commands/Debit.sol +5 -7
- package/commands/Deposit.sol +10 -14
- package/commands/Payout.sol +5 -8
- package/commands/Provision.sol +10 -14
- package/commands/Recover.sol +4 -6
- package/commands/Relay.sol +16 -22
- package/commands/Repay.sol +10 -14
- package/commands/Settle.sol +10 -14
- package/commands/Withdraw.sol +5 -7
- package/commands/admin/AllowAssets.sol +5 -7
- package/commands/admin/Allowance.sol +5 -7
- package/commands/admin/Annotate.sol +5 -7
- package/commands/admin/Appoint.sol +5 -7
- package/commands/admin/Authorize.sol +5 -7
- package/commands/admin/Base.sol +12 -3
- package/commands/admin/DenyAssets.sol +5 -7
- package/commands/admin/Dismiss.sol +5 -7
- package/commands/admin/Execute.sol +5 -7
- package/commands/admin/Unauthorize.sol +5 -7
- package/core/Calls.sol +72 -3
- package/core/Host.sol +7 -10
- package/core/Portal.sol +2 -2
- package/events/Dispatch.sol +1 -1
- package/events/Positioned.sol +22 -0
- package/events/Relay.sol +1 -1
- package/events/Route.sol +1 -1
- package/execution/Execution.sol +124 -4
- package/package.json +2 -3
- package/ports/Allowance.sol +22 -12
- package/ports/Assets.sol +99 -0
- package/ports/Dispatch.sol +2 -1
- package/utils/Cursors.sol +3 -3
- package/utils/Nodes.sol +1 -1
- package/utils/Utils.sol +31 -31
- package/docs/Schema.md +0 -427
- package/events/Commander.sol +0 -19
- package/ports/AllowAssets.sol +0 -34
- package/ports/DenyAssets.sol +0 -34
package/ports/Allowance.sol
CHANGED
|
@@ -2,35 +2,45 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
|
-
import {AllowanceHook} from "../commands/admin/Allowance.sol";
|
|
6
5
|
import {Specs} from "../Codec.sol";
|
|
7
6
|
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
8
7
|
|
|
9
8
|
using Executions for Execution;
|
|
10
9
|
|
|
11
|
-
/// @
|
|
12
|
-
|
|
13
|
-
///
|
|
14
|
-
///
|
|
15
|
-
|
|
10
|
+
/// @notice Hook implemented by hosts that handle allowance requests from peers.
|
|
11
|
+
abstract contract RequestAllowanceHook {
|
|
12
|
+
/// @notice Override to handle one allowance request from a peer host.
|
|
13
|
+
/// @dev The implementation is responsible for validating the request and
|
|
14
|
+
/// deciding what allowance, if any, to grant.
|
|
15
|
+
/// @param peer Peer host node ID requesting the allowance.
|
|
16
|
+
/// @param asset Asset identifier supplied by the peer.
|
|
17
|
+
/// @param amount Allowance amount requested in the asset's native units.
|
|
18
|
+
function requestAllowance(uint peer, bytes32 asset, uint amount) internal virtual;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// @title RequestAllowancePort
|
|
22
|
+
/// @notice Port that lets trusted peers request their own asset allowances.
|
|
23
|
+
/// Each AMOUNT block is scoped to the caller and passed unchanged to
|
|
24
|
+
/// `requestAllowance(peer, asset, amount)`.
|
|
25
|
+
abstract contract RequestAllowancePort is PortBase, RequestAllowanceHook {
|
|
16
26
|
uint private immutable descriptor;
|
|
17
27
|
|
|
18
28
|
constructor() {
|
|
19
|
-
(, descriptor) = port("
|
|
29
|
+
(, descriptor) = port("portRequestAllowance", Specs.Amount, Specs.Empty, 0);
|
|
20
30
|
}
|
|
21
31
|
|
|
22
|
-
/// @notice
|
|
23
|
-
/// @param data AMOUNT block stream
|
|
32
|
+
/// @notice Request asset allowances for the calling peer.
|
|
33
|
+
/// @param data AMOUNT block stream supplied by the trusted peer.
|
|
24
34
|
/// @return Empty response bytes.
|
|
25
|
-
function
|
|
35
|
+
function portRequestAllowance(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
26
36
|
Execution memory exec = openInput(data, descriptor, 0);
|
|
27
37
|
uint peer = caller();
|
|
28
38
|
|
|
29
39
|
while (exec.more()) {
|
|
30
40
|
(bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
|
|
31
|
-
|
|
41
|
+
requestAllowance(peer, asset, amount);
|
|
32
42
|
}
|
|
33
|
-
|
|
43
|
+
|
|
34
44
|
return "";
|
|
35
45
|
}
|
|
36
46
|
}
|
package/ports/Assets.sol
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {PortBase} from "./Base.sol";
|
|
5
|
+
import {AllowAssetsHook} from "../commands/admin/AllowAssets.sol";
|
|
6
|
+
import {DenyAssetsHook} from "../commands/admin/DenyAssets.sol";
|
|
7
|
+
import {Specs} from "../Codec.sol";
|
|
8
|
+
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
9
|
+
|
|
10
|
+
using Executions for Execution;
|
|
11
|
+
|
|
12
|
+
/// @title AllowAssetsPort
|
|
13
|
+
/// @notice Port that permits a list of assets on behalf of a peer host.
|
|
14
|
+
/// Each ASSET block in the input calls `allowAsset`. Restricted to trusted peers.
|
|
15
|
+
abstract contract AllowAssetsPort is PortBase, AllowAssetsHook {
|
|
16
|
+
uint private immutable descriptor;
|
|
17
|
+
|
|
18
|
+
constructor() {
|
|
19
|
+
(, descriptor) = port("portAllowAssets", Specs.Asset, Specs.Empty, 0);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// @notice Execute the allow-assets peer call.
|
|
23
|
+
/// @param data ASSET block stream supplied by the trusted peer.
|
|
24
|
+
/// @return Empty response bytes.
|
|
25
|
+
function portAllowAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
26
|
+
Execution memory exec = openInput(data, descriptor, 0);
|
|
27
|
+
|
|
28
|
+
while (exec.more()) {
|
|
29
|
+
bytes32 asset = exec.unpackAsset(Lanes.Input);
|
|
30
|
+
allowAsset(asset);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return "";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// @title DenyAssetsPort
|
|
38
|
+
/// @notice Port that blocks a list of assets on behalf of a peer host.
|
|
39
|
+
/// Each ASSET block in the input calls `denyAsset`. Restricted to trusted peers.
|
|
40
|
+
abstract contract DenyAssetsPort is PortBase, DenyAssetsHook {
|
|
41
|
+
uint private immutable descriptor;
|
|
42
|
+
|
|
43
|
+
constructor() {
|
|
44
|
+
(, descriptor) = port("portDenyAssets", Specs.Asset, Specs.Empty, 0);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/// @notice Execute the deny-assets peer call.
|
|
48
|
+
/// @param data ASSET block stream supplied by the trusted peer.
|
|
49
|
+
/// @return Empty response bytes.
|
|
50
|
+
function portDenyAssets(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
51
|
+
Execution memory exec = openInput(data, descriptor, 0);
|
|
52
|
+
|
|
53
|
+
while (exec.more()) {
|
|
54
|
+
bytes32 asset = exec.unpackAsset(Lanes.Input);
|
|
55
|
+
denyAsset(asset);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return "";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/// @notice Hook implemented by hosts that fulfill asset requests from peers.
|
|
63
|
+
abstract contract RequestAssetHook {
|
|
64
|
+
/// @notice Override to handle one asset request from a peer host.
|
|
65
|
+
/// @dev The implementation is responsible for validating `asset`, enforcing
|
|
66
|
+
/// requester policy, and sending the approved amount to the requester.
|
|
67
|
+
/// @param peer Peer host node ID for this request.
|
|
68
|
+
/// @param asset Asset identifier supplied by the peer.
|
|
69
|
+
/// @param amount Amount requested in the asset's native units.
|
|
70
|
+
function requestAsset(uint peer, bytes32 asset, uint amount) internal virtual;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/// @title RequestAssetPort
|
|
74
|
+
/// @notice Port that lets trusted peers request assets from the receiving host.
|
|
75
|
+
/// Each AMOUNT block is scoped to the caller and passed unchanged to
|
|
76
|
+
/// `requestAsset(peer, asset, amount)`. The hook validates support and performs
|
|
77
|
+
/// any accounting and transfer required by the host.
|
|
78
|
+
abstract contract RequestAssetPort is PortBase, RequestAssetHook {
|
|
79
|
+
uint private immutable descriptor;
|
|
80
|
+
|
|
81
|
+
constructor() {
|
|
82
|
+
(, descriptor) = port("portRequestAsset", Specs.Amount, Specs.Empty, 0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// @notice Request assets for the calling peer.
|
|
86
|
+
/// @param data AMOUNT block stream supplied by the trusted peer.
|
|
87
|
+
/// @return Empty response bytes.
|
|
88
|
+
function portRequestAsset(bytes calldata data) external onlyPeer returns (bytes memory) {
|
|
89
|
+
Execution memory exec = openInput(data, descriptor, 0);
|
|
90
|
+
uint peer = caller();
|
|
91
|
+
|
|
92
|
+
while (exec.more()) {
|
|
93
|
+
(bytes32 asset, uint amount) = exec.unpackAmount(Lanes.Input);
|
|
94
|
+
requestAsset(peer, asset, amount);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return "";
|
|
98
|
+
}
|
|
99
|
+
}
|
package/ports/Dispatch.sol
CHANGED
|
@@ -11,7 +11,8 @@ using Executions for Execution;
|
|
|
11
11
|
/// @notice Hook implemented by hosts that forward funded dispatch payloads.
|
|
12
12
|
abstract contract DispatchPayableHook {
|
|
13
13
|
/// @notice Override to dispatch an encoded payload to `portal`.
|
|
14
|
-
/// @param portal Destination portal
|
|
14
|
+
/// @param portal Destination portal implementation's host ID. Implementations
|
|
15
|
+
/// may validate or resolve it for their transport.
|
|
15
16
|
/// @param resources Chain-specific destination resources. EVM adapters
|
|
16
17
|
/// may interpret this as packed execution gas and destination value.
|
|
17
18
|
/// @param payload Encoded payload ready for the transport layer.
|
package/utils/Cursors.sol
CHANGED
|
@@ -65,9 +65,9 @@ library Cursors {
|
|
|
65
65
|
/// @param tag Cursor identity tag.
|
|
66
66
|
/// @return cur Packed cursor.
|
|
67
67
|
function create(uint offset, uint len, uint items, uint8 flags, uint8 tag) internal pure returns (uint cur) {
|
|
68
|
-
cur |= max32(offset) << 32;
|
|
69
|
-
cur |= max32(len) << 64;
|
|
70
|
-
cur |= max16(items) << 96;
|
|
68
|
+
cur |= uint(max32(offset)) << 32;
|
|
69
|
+
cur |= uint(max32(len)) << 64;
|
|
70
|
+
cur |= uint(max16(items)) << 96;
|
|
71
71
|
cur |= uint(flags) << 112;
|
|
72
72
|
cur |= uint(tag) << 120;
|
|
73
73
|
}
|
package/utils/Nodes.sol
CHANGED
|
@@ -198,7 +198,7 @@ library Nodes {
|
|
|
198
198
|
/// @return node Command node ID embedding both the selector and address.
|
|
199
199
|
function toCommand(string memory name, address target) internal view returns (uint node) {
|
|
200
200
|
node = toLocalBase(Command) | uint(uint160(target));
|
|
201
|
-
node |= uint(uint32(toSelector(name, "(
|
|
201
|
+
node |= uint(uint32(toSelector(name, "(bytes)"))) << 160;
|
|
202
202
|
}
|
|
203
203
|
|
|
204
204
|
/// @notice Build a chain-local port ID for the given endpoint name and contract.
|
package/utils/Utils.sol
CHANGED
|
@@ -11,76 +11,76 @@ 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
13
|
|
|
14
|
-
/// @notice Assert that `value` fits in uint8 and return it
|
|
15
|
-
function max8(uint value) pure returns (
|
|
14
|
+
/// @notice Assert that `value` fits in uint8 and return it as uint8.
|
|
15
|
+
function max8(uint value) pure returns (uint8) {
|
|
16
16
|
if (value > type(uint8).max) {
|
|
17
17
|
revert ValueOverflow();
|
|
18
18
|
}
|
|
19
|
-
return value;
|
|
19
|
+
return uint8(value);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
/// @notice Assert that `value` fits in uint16 and return it
|
|
23
|
-
function max16(uint value) pure returns (
|
|
22
|
+
/// @notice Assert that `value` fits in uint16 and return it as uint16.
|
|
23
|
+
function max16(uint value) pure returns (uint16) {
|
|
24
24
|
if (value > type(uint16).max) {
|
|
25
25
|
revert ValueOverflow();
|
|
26
26
|
}
|
|
27
|
-
return value;
|
|
27
|
+
return uint16(value);
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
/// @notice Assert that `value` fits in uint24 and return it
|
|
31
|
-
function max24(uint value) pure returns (
|
|
30
|
+
/// @notice Assert that `value` fits in uint24 and return it as uint24.
|
|
31
|
+
function max24(uint value) pure returns (uint24) {
|
|
32
32
|
if (value > type(uint24).max) {
|
|
33
33
|
revert ValueOverflow();
|
|
34
34
|
}
|
|
35
|
-
return value;
|
|
35
|
+
return uint24(value);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
/// @notice Assert that `value` fits in uint32 and return it
|
|
39
|
-
function max32(uint value) pure returns (
|
|
38
|
+
/// @notice Assert that `value` fits in uint32 and return it as uint32.
|
|
39
|
+
function max32(uint value) pure returns (uint32) {
|
|
40
40
|
if (value > type(uint32).max) {
|
|
41
41
|
revert ValueOverflow();
|
|
42
42
|
}
|
|
43
|
-
return value;
|
|
43
|
+
return uint32(value);
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
/// @notice Assert that `value` fits in uint40 and return it
|
|
47
|
-
function max40(uint value) pure returns (
|
|
46
|
+
/// @notice Assert that `value` fits in uint40 and return it as uint40.
|
|
47
|
+
function max40(uint value) pure returns (uint40) {
|
|
48
48
|
if (value > type(uint40).max) {
|
|
49
49
|
revert ValueOverflow();
|
|
50
50
|
}
|
|
51
|
-
return value;
|
|
51
|
+
return uint40(value);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
/// @notice Assert that `value` fits in uint64 and return it
|
|
55
|
-
function max64(uint value) pure returns (
|
|
54
|
+
/// @notice Assert that `value` fits in uint64 and return it as uint64.
|
|
55
|
+
function max64(uint value) pure returns (uint64) {
|
|
56
56
|
if (value > type(uint64).max) {
|
|
57
57
|
revert ValueOverflow();
|
|
58
58
|
}
|
|
59
|
-
return value;
|
|
59
|
+
return uint64(value);
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
/// @notice Assert that `value` fits in uint96 and return it
|
|
63
|
-
function max96(uint value) pure returns (
|
|
62
|
+
/// @notice Assert that `value` fits in uint96 and return it as uint96.
|
|
63
|
+
function max96(uint value) pure returns (uint96) {
|
|
64
64
|
if (value > type(uint96).max) {
|
|
65
65
|
revert ValueOverflow();
|
|
66
66
|
}
|
|
67
|
-
return value;
|
|
67
|
+
return uint96(value);
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
/// @notice Assert that `value` fits in uint128 and return it
|
|
71
|
-
function max128(uint value) pure returns (
|
|
70
|
+
/// @notice Assert that `value` fits in uint128 and return it as uint128.
|
|
71
|
+
function max128(uint value) pure returns (uint128) {
|
|
72
72
|
if (value > type(uint128).max) {
|
|
73
73
|
revert ValueOverflow();
|
|
74
74
|
}
|
|
75
|
-
return value;
|
|
75
|
+
return uint128(value);
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
/// @notice Assert that `value` fits in uint160 and return it
|
|
79
|
-
function max160(uint value) pure returns (
|
|
78
|
+
/// @notice Assert that `value` fits in uint160 and return it as uint160.
|
|
79
|
+
function max160(uint value) pure returns (uint160) {
|
|
80
80
|
if (value > type(uint160).max) {
|
|
81
81
|
revert ValueOverflow();
|
|
82
82
|
}
|
|
83
|
-
return value;
|
|
83
|
+
return uint160(value);
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
// Packed fields
|
|
@@ -108,25 +108,25 @@ function clear64(uint value, uint shift) pure returns (uint) {
|
|
|
108
108
|
/// @notice Replace the 8-bit field beginning at `shift` with `field`.
|
|
109
109
|
/// @dev Reverts when `field` does not fit in 8 bits.
|
|
110
110
|
function replace8(uint value, uint shift, uint field) pure returns (uint) {
|
|
111
|
-
return clear8(value, shift) | (max8(field) << shift);
|
|
111
|
+
return clear8(value, shift) | (uint(max8(field)) << shift);
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/// @notice Replace the 16-bit field beginning at `shift` with `field`.
|
|
115
115
|
/// @dev Reverts when `field` does not fit in 16 bits.
|
|
116
116
|
function replace16(uint value, uint shift, uint field) pure returns (uint) {
|
|
117
|
-
return clear16(value, shift) | (max16(field) << shift);
|
|
117
|
+
return clear16(value, shift) | (uint(max16(field)) << shift);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
/// @notice Replace the 32-bit field beginning at `shift` with `field`.
|
|
121
121
|
/// @dev Reverts when `field` does not fit in 32 bits.
|
|
122
122
|
function replace32(uint value, uint shift, uint field) pure returns (uint) {
|
|
123
|
-
return clear32(value, shift) | (max32(field) << shift);
|
|
123
|
+
return clear32(value, shift) | (uint(max32(field)) << shift);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
126
|
/// @notice Replace the 64-bit field beginning at `shift` with `field`.
|
|
127
127
|
/// @dev Reverts when `field` does not fit in 64 bits.
|
|
128
128
|
function replace64(uint value, uint shift, uint field) pure returns (uint) {
|
|
129
|
-
return clear64(value, shift) | (max64(field) << shift);
|
|
129
|
+
return clear64(value, shift) | (uint(max64(field)) << shift);
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
/// @notice Assert that `n` is evenly divisible by `divisor`.
|