@crossecute/protocol 0.0.0-stage → 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.
- package/README.md +26 -2
- package/abi/Blake2b256.json +1 -0
- package/abi/Blake2bScheme.json +1 -0
- package/abi/ChainRegistry.json +1 -0
- package/abi/Commitment.json +1 -0
- package/abi/Conduits.json +1 -0
- package/abi/DivergentConduits.json +1 -0
- package/abi/DivergentTransceiver.json +1 -0
- package/abi/DivergentTransceiverExtension.json +1 -0
- package/abi/Envelope.json +1 -0
- package/abi/Erc7930.json +1 -0
- package/abi/Executor.json +1 -0
- package/abi/IBootstrapAllowlist.json +1 -0
- package/abi/ICancel.json +1 -0
- package/abi/IChainRegistryRefs.json +1 -0
- package/abi/ICommitFinalize.json +1 -0
- package/abi/ICommitmentScheme.json +1 -0
- package/abi/IConduitReceiverReport.json +1 -0
- package/abi/IConduitTransceiver.json +1 -0
- package/abi/IERC7786GatewaySource.json +1 -0
- package/abi/IERC7786Recipient.json +1 -0
- package/abi/IExecute.json +1 -0
- package/abi/ILzOftConduitFactory.json +1 -0
- package/abi/IProviderIdTable.json +1 -0
- package/abi/IProxy.json +1 -0
- package/abi/IReceiverInit.json +1 -0
- package/abi/IRefValidator.json +1 -0
- package/abi/IReportFloat.json +1 -0
- package/abi/ITransmitterInit.json +1 -0
- package/abi/IVmDeriver.json +1 -0
- package/abi/KeccakScheme.json +1 -0
- package/abi/Move.json +1 -0
- package/abi/MoveValidator.json +1 -0
- package/abi/OpStackTransmitterBase.json +1 -0
- package/abi/OutboundBase.json +1 -0
- package/abi/OwnableTransmitter.json +1 -0
- package/abi/ProviderAddress.json +1 -0
- package/abi/ProviderAttribute.json +1 -0
- package/abi/ProviderChainId.json +1 -0
- package/abi/ProviderReceiver.json +1 -0
- package/abi/ProviderTransceiver.json +1 -0
- package/abi/Proxy.json +1 -0
- package/abi/ProxyDeployer.json +1 -0
- package/abi/ProxyInitCode.json +1 -0
- package/abi/ReceiverBase.json +1 -0
- package/abi/Roles.json +1 -0
- package/abi/RolesEnumerable.json +1 -0
- package/abi/SchemeFold.json +1 -0
- package/abi/Sha256Scheme.json +1 -0
- package/abi/StarknetDerive.json +1 -0
- package/abi/StarknetValidator.json +1 -0
- package/abi/SuiDerive.json +1 -0
- package/abi/TransceiverBase.json +1 -0
- package/abi/TransceiverCore.json +1 -0
- package/abi/TransceiverExtension.json +1 -0
- package/abi/TransmitterBase.json +1 -0
- package/abi/Treasury.json +1 -0
- package/abi/TronConduits.json +1 -0
- package/abi/TronTransceiver.json +1 -0
- package/abi/TronTransceiverExtension.json +1 -0
- package/abi/VmDeriver.json +1 -0
- package/abi/ZkSyncConduits.json +1 -0
- package/abi/ZkSyncTransceiver.json +1 -0
- package/abi/ZkSyncTransceiverExtension.json +1 -0
- package/abi/index.d.ts +63 -0
- package/abi/index.js +63 -0
- package/contracts/addressing/ChainKey.sol +45 -0
- package/contracts/addressing/ChainType.sol +50 -0
- package/contracts/addressing/Erc7930.sol +209 -0
- package/contracts/addressing/Move.sol +212 -0
- package/contracts/conduit/Conduits.sol +43 -0
- package/contracts/conduit/Proxy.sol +144 -0
- package/contracts/conduit/ProxyDeployer.sol +42 -0
- package/contracts/conduit/ProxyInitCode.sol +47 -0
- package/contracts/derivation/AddressDerive.sol +326 -0
- package/contracts/derivation/BitcoinDerive.sol +33 -0
- package/contracts/derivation/Blake2b256.sol +122 -0
- package/contracts/derivation/IVmDeriver.sol +35 -0
- package/contracts/derivation/StarknetDerive.sol +93 -0
- package/contracts/derivation/SuiDerive.sol +102 -0
- package/contracts/derivation/VmDeriver.sol +291 -0
- package/contracts/messaging/Call.sol +43 -0
- package/contracts/messaging/Commitment.sol +131 -0
- package/contracts/messaging/DeliveryGas.sol +18 -0
- package/contracts/messaging/Envelope.sol +123 -0
- package/contracts/messaging/Executor.sol +52 -0
- package/contracts/messaging/IErc7786.sol +68 -0
- package/contracts/messaging/Payload.sol +90 -0
- package/contracts/messaging/Roles.sol +113 -0
- package/contracts/messaging/inbound/ReceiverBase.sol +359 -0
- package/contracts/messaging/outbound/OutboundBase.sol +221 -0
- package/contracts/messaging/outbound/OwnableTransmitter.sol +23 -0
- package/contracts/messaging/outbound/TransmitterBase.sol +604 -0
- package/contracts/messaging/transceiver/DivergentConduits.sol +92 -0
- package/contracts/messaging/transceiver/DivergentTransceiver.sol +97 -0
- package/contracts/messaging/transceiver/IBootstrapAllowlist.sol +8 -0
- package/contracts/messaging/transceiver/TransceiverBase.sol +541 -0
- package/contracts/messaging/transceiver/TransceiverCore.sol +307 -0
- package/contracts/messaging/transceiver/TransceiverExtension.sol +278 -0
- package/contracts/protocols/ProviderAddress.sol +32 -0
- package/contracts/protocols/ProviderAttribute.sol +65 -0
- package/contracts/protocols/ProviderChainId.sol +115 -0
- package/contracts/protocols/ProviderReceiver.sol +24 -0
- package/contracts/protocols/ProviderTransceiver.sol +48 -0
- package/contracts/protocols/layerzero/ILzOftConduitFactory.sol +10 -0
- package/contracts/protocols/op-stack/OpStackTransmitterBase.sol +11 -0
- package/contracts/registry/ChainRegistry.sol +667 -0
- package/contracts/registry/IChainRegistryRefs.sol +81 -0
- package/contracts/registry/ICommitmentScheme.sol +46 -0
- package/contracts/registry/IRefValidator.sol +13 -0
- package/contracts/registry/Provenance.sol +25 -0
- package/contracts/schemes/Blake2bScheme.sol +18 -0
- package/contracts/schemes/KeccakScheme.sol +19 -0
- package/contracts/schemes/Sha256Scheme.sol +15 -0
- package/contracts/treasury/Treasury.sol +76 -0
- package/contracts/validators/MoveValidator.sol +24 -0
- package/contracts/validators/StarknetValidator.sol +20 -0
- package/package.json +36 -4
|
@@ -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
|
+
}
|