@crossecute/protocol 0.0.0 → 0.1.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 (118) hide show
  1. package/README.md +25 -1
  2. package/abi/Blake2b256.json +1 -0
  3. package/abi/Blake2bScheme.json +1 -0
  4. package/abi/ChainRegistry.json +1 -0
  5. package/abi/Commitment.json +1 -0
  6. package/abi/Conduits.json +1 -0
  7. package/abi/DivergentConduits.json +1 -0
  8. package/abi/DivergentTransceiver.json +1 -0
  9. package/abi/DivergentTransceiverExtension.json +1 -0
  10. package/abi/Envelope.json +1 -0
  11. package/abi/Erc7930.json +1 -0
  12. package/abi/Executor.json +1 -0
  13. package/abi/IBootstrapAllowlist.json +1 -0
  14. package/abi/ICancel.json +1 -0
  15. package/abi/IChainRegistryRefs.json +1 -0
  16. package/abi/ICommitFinalize.json +1 -0
  17. package/abi/ICommitmentScheme.json +1 -0
  18. package/abi/IConduitReceiverReport.json +1 -0
  19. package/abi/IConduitTransceiver.json +1 -0
  20. package/abi/IERC7786GatewaySource.json +1 -0
  21. package/abi/IERC7786Recipient.json +1 -0
  22. package/abi/IExecute.json +1 -0
  23. package/abi/ILzOftConduitFactory.json +1 -0
  24. package/abi/IProviderIdTable.json +1 -0
  25. package/abi/IProxy.json +1 -0
  26. package/abi/IReceiverInit.json +1 -0
  27. package/abi/IRefValidator.json +1 -0
  28. package/abi/IReportFloat.json +1 -0
  29. package/abi/ITransmitterInit.json +1 -0
  30. package/abi/IVmDeriver.json +1 -0
  31. package/abi/KeccakScheme.json +1 -0
  32. package/abi/Move.json +1 -0
  33. package/abi/MoveValidator.json +1 -0
  34. package/abi/OpStackTransmitterBase.json +1 -0
  35. package/abi/OutboundBase.json +1 -0
  36. package/abi/OwnableTransmitter.json +1 -0
  37. package/abi/ProviderAddress.json +1 -0
  38. package/abi/ProviderAttribute.json +1 -0
  39. package/abi/ProviderChainId.json +1 -0
  40. package/abi/ProviderReceiver.json +1 -0
  41. package/abi/ProviderTransceiver.json +1 -0
  42. package/abi/Proxy.json +1 -0
  43. package/abi/ProxyDeployer.json +1 -0
  44. package/abi/ProxyInitCode.json +1 -0
  45. package/abi/ReceiverBase.json +1 -0
  46. package/abi/Roles.json +1 -0
  47. package/abi/RolesEnumerable.json +1 -0
  48. package/abi/SchemeFold.json +1 -0
  49. package/abi/Sha256Scheme.json +1 -0
  50. package/abi/StarknetDerive.json +1 -0
  51. package/abi/StarknetValidator.json +1 -0
  52. package/abi/SuiDerive.json +1 -0
  53. package/abi/TransceiverBase.json +1 -0
  54. package/abi/TransceiverCore.json +1 -0
  55. package/abi/TransceiverExtension.json +1 -0
  56. package/abi/TransmitterBase.json +1 -0
  57. package/abi/Treasury.json +1 -0
  58. package/abi/TronConduits.json +1 -0
  59. package/abi/TronTransceiver.json +1 -0
  60. package/abi/TronTransceiverExtension.json +1 -0
  61. package/abi/VmDeriver.json +1 -0
  62. package/abi/ZkSyncConduits.json +1 -0
  63. package/abi/ZkSyncTransceiver.json +1 -0
  64. package/abi/ZkSyncTransceiverExtension.json +1 -0
  65. package/abi/index.d.ts +63 -0
  66. package/abi/index.js +63 -0
  67. package/contracts/addressing/ChainKey.sol +45 -0
  68. package/contracts/addressing/ChainType.sol +50 -0
  69. package/contracts/addressing/Erc7930.sol +209 -0
  70. package/contracts/addressing/Move.sol +212 -0
  71. package/contracts/conduit/Conduits.sol +43 -0
  72. package/contracts/conduit/Proxy.sol +144 -0
  73. package/contracts/conduit/ProxyDeployer.sol +42 -0
  74. package/contracts/conduit/ProxyInitCode.sol +47 -0
  75. package/contracts/derivation/AddressDerive.sol +326 -0
  76. package/contracts/derivation/BitcoinDerive.sol +33 -0
  77. package/contracts/derivation/Blake2b256.sol +122 -0
  78. package/contracts/derivation/IVmDeriver.sol +35 -0
  79. package/contracts/derivation/StarknetDerive.sol +93 -0
  80. package/contracts/derivation/SuiDerive.sol +102 -0
  81. package/contracts/derivation/VmDeriver.sol +291 -0
  82. package/contracts/messaging/Call.sol +43 -0
  83. package/contracts/messaging/Commitment.sol +131 -0
  84. package/contracts/messaging/DeliveryGas.sol +18 -0
  85. package/contracts/messaging/Envelope.sol +123 -0
  86. package/contracts/messaging/Executor.sol +52 -0
  87. package/contracts/messaging/IErc7786.sol +68 -0
  88. package/contracts/messaging/Payload.sol +90 -0
  89. package/contracts/messaging/Roles.sol +113 -0
  90. package/contracts/messaging/inbound/ReceiverBase.sol +359 -0
  91. package/contracts/messaging/outbound/OutboundBase.sol +221 -0
  92. package/contracts/messaging/outbound/OwnableTransmitter.sol +23 -0
  93. package/contracts/messaging/outbound/TransmitterBase.sol +604 -0
  94. package/contracts/messaging/transceiver/DivergentConduits.sol +92 -0
  95. package/contracts/messaging/transceiver/DivergentTransceiver.sol +97 -0
  96. package/contracts/messaging/transceiver/IBootstrapAllowlist.sol +8 -0
  97. package/contracts/messaging/transceiver/TransceiverBase.sol +541 -0
  98. package/contracts/messaging/transceiver/TransceiverCore.sol +307 -0
  99. package/contracts/messaging/transceiver/TransceiverExtension.sol +278 -0
  100. package/contracts/protocols/ProviderAddress.sol +32 -0
  101. package/contracts/protocols/ProviderAttribute.sol +65 -0
  102. package/contracts/protocols/ProviderChainId.sol +115 -0
  103. package/contracts/protocols/ProviderReceiver.sol +24 -0
  104. package/contracts/protocols/ProviderTransceiver.sol +48 -0
  105. package/contracts/protocols/layerzero/ILzOftConduitFactory.sol +10 -0
  106. package/contracts/protocols/op-stack/OpStackTransmitterBase.sol +11 -0
  107. package/contracts/registry/ChainRegistry.sol +667 -0
  108. package/contracts/registry/IChainRegistryRefs.sol +81 -0
  109. package/contracts/registry/ICommitmentScheme.sol +46 -0
  110. package/contracts/registry/IRefValidator.sol +13 -0
  111. package/contracts/registry/Provenance.sol +25 -0
  112. package/contracts/schemes/Blake2bScheme.sol +18 -0
  113. package/contracts/schemes/KeccakScheme.sol +19 -0
  114. package/contracts/schemes/Sha256Scheme.sol +15 -0
  115. package/contracts/treasury/Treasury.sol +76 -0
  116. package/contracts/validators/MoveValidator.sol +24 -0
  117. package/contracts/validators/StarknetValidator.sol +20 -0
  118. package/package.json +34 -3
@@ -0,0 +1,65 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ /// @notice Parsing for the single selector-prefixed attribute each native binding accepts.
5
+ /// ERC-7786 requires a gateway to refuse any attribute it does not support.
6
+ /// @dev `attributes[0]` is validated in full (selector, length, and for `uintValue` the bound)
7
+ /// before a second attribute is refused, so a malformed first attribute is the one
8
+ /// reported rather than a well-formed extra.
9
+ library ProviderAttribute {
10
+ error UnsupportedAttribute(bytes attribute);
11
+
12
+ /// @notice The bytes after `selector` in the single attribute, or `present == false` when
13
+ /// none was given.
14
+ /// @param bodyLength The exact body length required; zero accepts any length.
15
+ function body(bytes[] memory attributes, bytes4 selector, uint256 bodyLength)
16
+ internal
17
+ pure
18
+ returns (bool present, bytes memory out)
19
+ {
20
+ // forge-lint: disable-next-line(boolean-cst) the `present` flag
21
+ if (attributes.length == 0) return (false, "");
22
+ bytes memory attribute = attributes[0];
23
+ if (
24
+ attribute.length < 4 || _selectorOf(attribute) != selector
25
+ || (bodyLength != 0 && attribute.length - 4 != bodyLength)
26
+ ) revert UnsupportedAttribute(attribute);
27
+ if (attributes.length > 1) revert UnsupportedAttribute(attributes[1]);
28
+
29
+ out = new bytes(attribute.length - 4);
30
+ for (uint256 i; i < out.length; ++i) {
31
+ out[i] = attribute[i + 4];
32
+ }
33
+ // forge-lint: disable-next-line(boolean-cst) the `present` flag
34
+ return (true, out);
35
+ }
36
+
37
+ /// @notice The `uint256` in a single `abi.encodePacked(selector, abi.encode(value))`
38
+ /// attribute, at most `max`, or `defaultValue` when none was given.
39
+ function uintValue(bytes[] memory attributes, bytes4 selector, uint256 max, uint256 defaultValue)
40
+ internal
41
+ pure
42
+ returns (uint256 value)
43
+ {
44
+ if (attributes.length == 0) return defaultValue;
45
+ bytes memory attribute = attributes[0];
46
+ if (attribute.length != 36 || _selectorOf(attribute) != selector) revert UnsupportedAttribute(attribute);
47
+ assembly {
48
+ value := mload(add(attribute, 36))
49
+ }
50
+ if (value > max) revert UnsupportedAttribute(attribute);
51
+ if (attributes.length > 1) revert UnsupportedAttribute(attributes[1]);
52
+ }
53
+
54
+ /// @notice For a binding that supports no attribute: the first given is refused.
55
+ function none(bytes[] memory attributes) internal pure {
56
+ if (attributes.length != 0) revert UnsupportedAttribute(attributes[0]);
57
+ }
58
+
59
+ /// @dev Callers check `attribute.length >= 4` first.
60
+ function _selectorOf(bytes memory attribute) private pure returns (bytes4 selector) {
61
+ assembly {
62
+ selector := mload(add(attribute, 32))
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,115 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {Erc7930} from "../addressing/Erc7930.sol";
5
+
6
+ /// @notice What a transmitter reads from its transceiver. It keeps no table of its own, being
7
+ /// per-user and locked after creation, so every send reads the transceiver's live.
8
+ interface IProviderIdTable {
9
+ function providerIdFor(bytes32 chainKey) external view returns (uint256);
10
+ }
11
+
12
+ /// @notice `recipient`'s provider id from `transceiver`'s table, for the caller to narrow to its
13
+ /// width.
14
+ function providerIdOf(address transceiver, bytes memory recipient) view returns (uint256) {
15
+ return IProviderIdTable(transceiver).providerIdFor(Erc7930.chainKey(recipient));
16
+ }
17
+
18
+ /// @title ProviderChainId
19
+ /// @notice Maps this protocol's chainKey to a native provider's own id for the same chain
20
+ /// (LayerZero's `uint32` eid, CCIP's `uint64` selector, Hyperlane's `uint32` domain).
21
+ ///
22
+ /// @dev Distinct from `ChainRegistry`, which answers a provenance question and has no
23
+ /// bearing here. A gateway binding (ERC-7786) never needs this file either: it's told
24
+ /// the chain by the recipient (see `OutboundBase`'s note on the route slot). Only the
25
+ /// native bindings under `protocols/` use it.
26
+ ///
27
+ /// @dev On every binding transceiver whose provider names chains by its own id. For
28
+ /// `op-stack-l1-l2` the id is the address of the messenger that reaches the chain.
29
+ ///
30
+ /// @dev Storage is `uint256` so one mapping backs every provider's narrower id type; each
31
+ /// binding's typed setter (`setEid`, `setSelector`, `setDomain`, `setWormholeChain`)
32
+ /// bounds it on the way in, and readers narrow it back.
33
+ ///
34
+ /// @dev Write-once-if-unset, same shape as `OutboundBase._setRoute`: re-declaring the same id
35
+ /// is a no-op, a different one reverts, since repointing would silently redirect future
36
+ /// sends to a different remote endpoint.
37
+ ///
38
+ /// @dev The reverse index exists because a provider's inbound callback reports the source by
39
+ /// its own id, not our chainKey. It is injective: two chainKeys sharing one provider id
40
+ /// would let an inbound message from either be attributed to the other. Routes get the
41
+ /// same property from `OutboundBase._setRoute`, which requires a route to hash to its key.
42
+ ///
43
+ /// @dev Zero is the unset sentinel on both sides, so a provider id of 0 is refused here
44
+ /// (`ZeroProviderId`) and in `deploy/` (`ChainConfig.providerId`).
45
+ ///
46
+ /// @dev Internal and ungated, like every other setter on `OutboundBase`: the inheriting
47
+ /// transceiver wraps `_setProviderId` in its own authority.
48
+ abstract contract ProviderChainId is IProviderIdTable {
49
+ /// chainKey => the provider's own id for that chain. Zero means unset.
50
+ mapping(bytes32 => uint256) private _providerIds;
51
+
52
+ /// The inbound direction: a delivery names its origin by the provider's id, and this is
53
+ /// the only way back to a chainKey.
54
+ mapping(uint256 => bytes32) private _chainKeyOfProviderId;
55
+
56
+ event ProviderIdSet(bytes32 indexed chainKey, uint256 providerId);
57
+
58
+ /// @dev Named distinctly from `OutboundBase.NoDestination`: every binding transceiver
59
+ /// inherits both and would otherwise collide on the name.
60
+ error NoProviderChainKey();
61
+ error ZeroProviderId();
62
+ error ProviderIdAlreadySet(bytes32 chainKey);
63
+ error ProviderIdInUse(uint256 providerId);
64
+ error NoProviderIdFor(bytes32 chainKey);
65
+ error UnknownProviderId(uint256 providerId);
66
+
67
+ /// @notice Write-once, ungated: the caller applies its own authority. See the
68
+ /// contract-level note for why re-declaring the same id is a no-op while a
69
+ /// different one reverts.
70
+ function _setProviderId(bytes32 chainKey, uint256 providerId) internal {
71
+ if (chainKey == bytes32(0)) revert NoProviderChainKey();
72
+ if (providerId == 0) revert ZeroProviderId();
73
+
74
+ uint256 existing = _providerIds[chainKey];
75
+ if (existing != 0) {
76
+ if (existing != providerId) revert ProviderIdAlreadySet(chainKey);
77
+ return;
78
+ }
79
+
80
+ bytes32 held = _chainKeyOfProviderId[providerId];
81
+ if (held != bytes32(0) && held != chainKey) revert ProviderIdInUse(providerId);
82
+
83
+ _providerIds[chainKey] = providerId;
84
+ _chainKeyOfProviderId[providerId] = chainKey;
85
+ emit ProviderIdSet(chainKey, providerId);
86
+ }
87
+
88
+ /// @notice The provider's id for `chainKey`. Reverts when unset.
89
+ function _providerIdFor(bytes32 chainKey) internal view returns (uint256 providerId) {
90
+ providerId = _providerIds[chainKey];
91
+ if (providerId == 0) revert NoProviderIdFor(chainKey);
92
+ }
93
+
94
+ /// @notice The chainKey a provider id refers to (inbound direction). Reverts when unset.
95
+ function _chainKeyOfProvider(uint256 providerId) internal view returns (bytes32 chainKey) {
96
+ chainKey = _chainKeyOfProviderId[providerId];
97
+ if (chainKey == bytes32(0)) revert UnknownProviderId(providerId);
98
+ }
99
+
100
+ /// @notice Whether a provider id is recorded for `chainKey`.
101
+ function hasProviderId(bytes32 chainKey) public view returns (bool) {
102
+ return _providerIds[chainKey] != 0;
103
+ }
104
+
105
+ /// @notice See `IProviderIdTable`. Reverts `NoProviderIdFor` when unset; the typed setters
106
+ /// are per binding.
107
+ function providerIdFor(bytes32 chainKey) external view returns (uint256) {
108
+ return _providerIdFor(chainKey);
109
+ }
110
+
111
+ /// @notice The provider's id for the chain `recipient` is on.
112
+ function _providerIdOf(bytes memory recipient) internal view returns (uint256) {
113
+ return _providerIdFor(Erc7930.chainKey(recipient));
114
+ }
115
+ }
@@ -0,0 +1,24 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {Call} from "../messaging/Call.sol";
5
+ import {ReceiverBase} from "../messaging/inbound/ReceiverBase.sol";
6
+
7
+ /// @notice A receiver whose only provider setup is naming the provider's delivery contract as
8
+ /// its gateway.
9
+ abstract contract ProviderReceiver is ReceiverBase {
10
+ /// @dev `_grantInitialRole` is `onlyInitializing`, so this initializer is the only window the
11
+ /// gateway grant ever gets. It runs before `__ReceiverBase_init`, which executes the
12
+ /// payload.
13
+ function initialize(address sourceTransmitter_, bytes32 homeOrigin_, Call[] calldata calls)
14
+ external
15
+ override
16
+ initializer
17
+ {
18
+ _grantInitialRole(GATEWAY_ROLE, _providerGateway());
19
+ __ReceiverBase_init(sourceTransmitter_, homeOrigin_, calls);
20
+ }
21
+
22
+ /// @notice The provider contract that delivers to this receiver.
23
+ function _providerGateway() internal view virtual returns (address);
24
+ }
@@ -0,0 +1,48 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {TransceiverBase} from "../messaging/transceiver/TransceiverBase.sol";
5
+ import {IReceiverInit} from "../messaging/inbound/ReceiverBase.sol";
6
+ import {ProviderChainId} from "./ProviderChainId.sol";
7
+ import {Call} from "../messaging/Call.sol";
8
+
9
+ /// @notice What every native binding with a provider chain id shares: the id table, and mapping
10
+ /// a delivery's reported origin back to a route, which `_authenticateOrigin` then
11
+ /// checks like any other.
12
+ abstract contract ProviderTransceiver is TransceiverBase, ProviderChainId {
13
+ /// @notice Name the provider's own delivery contract as a gateway, for a binding whose
14
+ /// entry point checks `GATEWAY_ROLE`.
15
+ function __ProviderTransceiver_init(address providerGateway) internal onlyInitializing {
16
+ _grantInitialRole(GATEWAY_ROLE, providerGateway);
17
+ }
18
+
19
+ /// @notice Name the provider's id for the governor's home, so the bootstrap that creates
20
+ /// this transceiver's owner can be accepted. Zero leaves it to the owner, which only
21
+ /// the governor's home can do.
22
+ function _initGovernorHomeId(bytes memory governorHome, uint256 providerId) internal onlyInitializing {
23
+ if (providerId != 0) _setProviderId(keccak256(governorHome), providerId);
24
+ }
25
+
26
+ /// @dev An unmapped `providerId` reverts in `_chainKeyOfProvider`, so a chain this
27
+ /// transceiver was never configured for cannot deliver at all.
28
+ function _onProviderInbound(uint256 providerId, address sender, bytes calldata message) internal {
29
+ _onInbound(routeFor(_chainKeyOfProvider(providerId)), abi.encodePacked(sender), message);
30
+ }
31
+
32
+ /// @inheritdoc TransceiverBase
33
+ /// @dev A receiver names its home by the provider's id for it, from the table that admitted
34
+ /// the bootstrap, since that is how its deliveries report their origin.
35
+ function _conduitInitializer(
36
+ address owner,
37
+ bytes32 salt,
38
+ bytes32 homeChainKey,
39
+ address sourceTransmitter,
40
+ Call[] memory calls
41
+ ) internal view virtual override returns (bytes memory) {
42
+ if (homeChainKey == localChainKey) {
43
+ return super._conduitInitializer(owner, salt, homeChainKey, sourceTransmitter, calls);
44
+ }
45
+ return
46
+ abi.encodeCall(IReceiverInit.initialize, (sourceTransmitter, bytes32(_providerIdFor(homeChainKey)), calls));
47
+ }
48
+ }
@@ -0,0 +1,10 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ /// @notice What a `layerzero-oft` conduit reads from the factory that created it, beyond the
5
+ /// views `TransmitterBase` reads from any transceiver.
6
+ interface ILzOftConduitFactory {
7
+ /// @notice The eid and OFT `conduit` reaches `chainKey` through, as it was created with.
8
+ /// @dev Reverts for a chain the conduit was not created with.
9
+ function destinationOf(address conduit, bytes32 chainKey) external view returns (uint32 eid, address oft);
10
+ }
@@ -0,0 +1,11 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.0;
3
+
4
+ import {OwnableTransmitter} from "../../messaging/outbound/OwnableTransmitter.sol";
5
+
6
+ /// @notice The fixed outbound fee shared by the two OP Stack bindings.
7
+ abstract contract OpStackTransmitterBase is OwnableTransmitter {
8
+ function _crossecuteFee(uint256) internal pure override returns (uint256) {
9
+ return 0.0001 ether;
10
+ }
11
+ }