Skip to content

Commit 721978d

Browse files
committed
Make NTT depositors fixed-destination
1 parent ff3c1d5 commit 721978d

28 files changed

Lines changed: 769 additions & 7017 deletions

solidity/contracts/cross-chain/wormhole/L1BTCDepositorNtt.sol

Lines changed: 36 additions & 196 deletions
Large diffs are not rendered by default.

solidity/contracts/cross-chain/wormhole/L1BTCDepositorNttWithExecutor.sol

Lines changed: 24 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
1919
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
2020

2121
import "../AbstractL1BTCDepositor.sol";
22-
import "./TransceiverStructs.sol";
2322

2423
/// @notice Executor arguments for NttManagerWithExecutor transfers
2524
/// @dev These parameters are used by the Wormhole Executor service
@@ -137,11 +136,8 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
137136
/// @dev This is passed to the NttManagerWithExecutor during transfers
138137
address public underlyingNttManager;
139138

140-
/// @notice Mapping of supported destination chains by Wormhole chain ID
141-
mapping(uint16 => bool) public supportedChains;
142-
143-
/// @notice Default supported chain ID for backward compatibility
144-
uint16 public defaultSupportedChain;
139+
/// @notice Wormhole chain ID of the configured destination chain.
140+
uint16 public destinationChainId;
145141

146142
/// @notice Default gas limit for destination chain execution
147143
/// @dev Used when no specific gas limit is provided in relay instructions
@@ -204,27 +200,21 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
204200
/// @notice Emitted when tokens are transferred via NTT Manager With Executor
205201
/// @param amount Amount of tBTC transferred
206202
/// @param destinationChain Wormhole chain ID of the destination
207-
/// @param actualRecipient Actual recipient address on destination chain
203+
/// @param recipient Recipient address on destination chain
208204
/// @param transferSequence NTT transfer sequence number
209-
/// @param encodedReceiver Original encoded receiver data
205+
/// @param destinationChainDepositOwner Original deposit extra data
210206
/// @param executorCost Cost paid to executor service in wei
211207
event TokensTransferredNttWithExecutor(
212208
address indexed sender,
213209
bytes32 indexed nonce,
214210
uint256 amount,
215211
uint16 destinationChain,
216-
bytes32 actualRecipient,
212+
bytes32 recipient,
217213
uint64 transferSequence,
218-
bytes32 encodedReceiver,
214+
bytes32 destinationChainDepositOwner,
219215
uint256 executorCost
220216
);
221217

222-
/// @notice Emitted when a destination chain is added or removed
223-
event SupportedChainUpdated(uint16 indexed chainId, bool supported);
224-
225-
/// @notice Emitted when default supported chain is updated
226-
event DefaultSupportedChainUpdated(uint16 indexed chainId);
227-
228218
/// @notice Emitted when default parameters are updated
229219
event DefaultParametersUpdated(
230220
uint256 gasLimit,
@@ -272,11 +262,13 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
272262
/// @param _tbtcVault tBTC Vault contract address
273263
/// @param _nttManagerWithExecutor NTT Manager With Executor contract address
274264
/// @param _underlyingNttManager Underlying NTT Manager contract address
265+
/// @param _destinationChainId Wormhole chain ID of the destination chain
275266
function initialize(
276267
address _tbtcBridge,
277268
address _tbtcVault,
278269
address _nttManagerWithExecutor,
279-
address _underlyingNttManager
270+
address _underlyingNttManager,
271+
uint16 _destinationChainId
280272
) external initializer {
281273
__AbstractL1BTCDepositor_initialize(_tbtcBridge, _tbtcVault);
282274
__Ownable_init();
@@ -289,11 +281,13 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
289281
_underlyingNttManager != address(0),
290282
"Underlying NTT Manager address cannot be zero"
291283
);
284+
require(_destinationChainId != 0, "Chain ID cannot be zero");
292285

293286
nttManagerWithExecutor = INttManagerWithExecutor(
294287
_nttManagerWithExecutor
295288
);
296289
underlyingNttManager = _underlyingNttManager;
290+
destinationChainId = _destinationChainId;
297291

298292
// Set reasonable defaults
299293
defaultDestinationGasLimit = DEFAULT_DESTINATION_GAS_LIMIT;
@@ -302,30 +296,6 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
302296
parameterExpirationTime = 3600; // 1 hour default expiration time
303297
}
304298

305-
/// @notice Sets the default supported chain for backward compatibility
306-
/// @param _chainId Wormhole chain ID to set as default
307-
function setDefaultSupportedChain(uint16 _chainId) external onlyOwner {
308-
require(_chainId != 0, "Chain ID cannot be zero");
309-
require(
310-
supportedChains[_chainId],
311-
"Chain must be supported before setting as default"
312-
);
313-
defaultSupportedChain = _chainId;
314-
emit DefaultSupportedChainUpdated(_chainId);
315-
}
316-
317-
/// @notice Adds or removes support for a destination chain
318-
/// @param _chainId Wormhole chain ID of the destination chain
319-
/// @param _supported Whether to support transfers to this chain
320-
function setSupportedChain(
321-
uint16 _chainId,
322-
bool _supported
323-
) external onlyOwner {
324-
require(_chainId != 0, "Chain ID cannot be zero");
325-
supportedChains[_chainId] = _supported;
326-
emit SupportedChainUpdated(_chainId, _supported);
327-
}
328-
329299
/// @notice Updates default parameters for executor transfers
330300
/// @param _gasLimit Default gas limit for destination chain execution
331301
/// @param _feeBps Default executor fee in basis points (max 10000 = 100%)
@@ -584,62 +554,23 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
584554
ExecutorParameterSet storage params = parametersByNonce[latestNonce];
585555
require(params.exists, "Executor parameters not set");
586556

587-
uint16 defaultChain = _getDefaultSupportedChain();
588-
require(defaultChain != 0, "No supported chains configured");
589-
590557
return
591558
nttManagerWithExecutor.quoteDeliveryPrice(
592559
underlyingNttManager,
593-
defaultChain,
594-
"",
595-
params.executorArgs,
596-
params.feeArgs
597-
);
598-
}
599-
600-
/// @notice Quotes cost for specific destination chain using latest parameters
601-
/// @param destinationChain Target chain ID
602-
/// @return cost Total cost for the transfer
603-
function quoteFinalizeDeposit(
604-
uint16 destinationChain
605-
) external view returns (uint256 cost) {
606-
require(
607-
userNonceCounter[msg.sender] > 0,
608-
"Executor parameters not set"
609-
);
610-
require(
611-
supportedChains[destinationChain],
612-
"Destination chain not supported"
613-
);
614-
615-
bytes32 latestNonce = _generateNonce(
616-
msg.sender,
617-
userNonceCounter[msg.sender] - 1
618-
);
619-
620-
ExecutorParameterSet storage params = parametersByNonce[latestNonce];
621-
require(params.exists, "Executor parameters not set");
622-
623-
return
624-
nttManagerWithExecutor.quoteDeliveryPrice(
625-
underlyingNttManager,
626-
destinationChain,
560+
destinationChainId,
627561
"",
628562
params.executorArgs,
629563
params.feeArgs
630564
);
631565
}
632566

633567
/// @notice Quotes the underlying NTT delivery price and total cost including executor fees
634-
/// @param destinationChain Target chain ID
635568
/// @return nttDeliveryPrice The NTT delivery price from the underlying manager
636569
/// @return executorCost The executor cost from the signed quote
637570
/// @return totalCost The total cost (NTT + executor)
638571
/// @dev This function calls the underlying NTT manager's quoteDeliveryPrice and returns
639572
/// the breakdown of costs. The caller should validate that their msg.value >= totalCost
640-
function quoteFinalizedDeposit(
641-
uint16 destinationChain
642-
)
573+
function quoteFinalizedDeposit()
643574
external
644575
view
645576
returns (
@@ -652,10 +583,6 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
652583
userNonceCounter[msg.sender] > 0,
653584
"Executor parameters not set"
654585
);
655-
require(
656-
supportedChains[destinationChain],
657-
"Destination chain not supported"
658-
);
659586

660587
bytes32 latestNonce = _generateNonce(
661588
msg.sender,
@@ -668,7 +595,7 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
668595
// Get NTT delivery price from underlying manager
669596
INttManager nttManager = INttManager(underlyingNttManager);
670597
(, nttDeliveryPrice) = nttManager.quoteDeliveryPrice(
671-
destinationChain,
598+
destinationChainId,
672599
"" // Empty transceiver instructions for basic transfer
673600
);
674601

@@ -817,10 +744,10 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
817744
/// @notice Transfers tBTC using NTT Manager With Executor for automatic destination execution
818745
/// @dev Uses the latest executor parameters for msg.sender (auto-nonce approach)
819746
/// @param amount Amount of tBTC to transfer
820-
/// @param destinationChainReceiver Encoded receiver data with chain ID and recipient
747+
/// @param destinationChainDepositOwner Full 32-byte recipient on the destination chain
821748
function _transferTbtc(
822749
uint256 amount,
823-
bytes32 destinationChainReceiver
750+
bytes32 destinationChainDepositOwner
824751
) internal override {
825752
require(
826753
userNonceCounter[msg.sender] > 0,
@@ -845,7 +772,7 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
845772
// Call internal transfer with stored parameters
846773
_transferTbtcWithExecutor(
847774
amount,
848-
destinationChainReceiver,
775+
destinationChainDepositOwner,
849776
params.executorArgs,
850777
params.feeArgs,
851778
latestNonce
@@ -857,14 +784,14 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
857784

858785
/// @notice Enhanced transfer function that requires real executor parameters
859786
/// @param amount Amount of tBTC to transfer
860-
/// @param destinationChainReceiver Encoded receiver data with chain ID and recipient
787+
/// @param destinationChainDepositOwner Full 32-byte recipient on the destination chain
861788
/// @param executorArgs Real executor arguments with valid signed quote
862789
/// @param feeArgs Fee arguments for the executor
863790
/// @param nonce The nonce used for this transfer
864791
// slither-disable-next-line reentrancy-vulnerabilities-3
865792
function _transferTbtcWithExecutor(
866793
uint256 amount,
867-
bytes32 destinationChainReceiver,
794+
bytes32 destinationChainDepositOwner,
868795
ExecutorArgs memory executorArgs,
869796
FeeArgs memory feeArgs,
870797
bytes32 nonce
@@ -873,19 +800,6 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
873800
// Event emission after external calls is correct pattern
874801
require(amount > 0, "Amount must be greater than 0");
875802

876-
// Extract destination chain and recipient
877-
uint16 destinationChain = _getDestinationChainFromReceiver(
878-
destinationChainReceiver
879-
);
880-
require(
881-
supportedChains[destinationChain],
882-
"Destination chain not supported"
883-
);
884-
885-
bytes32 actualRecipient = _getRecipientAddressFromReceiver(
886-
destinationChainReceiver
887-
);
888-
889803
// CRITICAL: Validate that we have a real signed quote
890804
require(
891805
executorArgs.signedQuote.length > 0,
@@ -909,8 +823,8 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
909823
uint64 sequence = nttManagerWithExecutor.transfer{value: msg.value}( // slither-disable-line reentrancy-vulnerabilities-3
910824
underlyingNttManager,
911825
amount,
912-
destinationChain,
913-
actualRecipient,
826+
destinationChainId,
827+
destinationChainDepositOwner,
914828
bytes32(uint256(uint160(msg.sender))), // refundAddress as bytes32
915829
"", // Empty transceiver instructions for basic transfer
916830
executorArgs,
@@ -921,57 +835,14 @@ contract L1BTCDepositorNttWithExecutor is AbstractL1BTCDepositor {
921835
msg.sender,
922836
nonce,
923837
amount,
924-
destinationChain,
925-
actualRecipient,
838+
destinationChainId,
839+
destinationChainDepositOwner,
926840
sequence,
927-
destinationChainReceiver,
841+
destinationChainDepositOwner,
928842
msg.value
929843
);
930844
}
931845

932-
/// @notice Extract destination chain from encoded receiver address
933-
/// @param destinationChainReceiver Encoded receiver with chain ID in first 2 bytes
934-
/// @return chainId The destination chain ID
935-
function _getDestinationChainFromReceiver(
936-
bytes32 destinationChainReceiver
937-
) internal view returns (uint16 chainId) {
938-
chainId = uint16(bytes2(destinationChainReceiver));
939-
940-
// CRITICAL: No fallback to default chain - user must specify valid chain
941-
if (chainId == 0) {
942-
revert("Chain ID cannot be zero");
943-
}
944-
945-
if (!supportedChains[chainId]) {
946-
revert("Destination chain not supported");
947-
}
948-
949-
return chainId;
950-
}
951-
952-
/// @notice Get the default supported chain ID
953-
/// @return chainId The default supported chain ID
954-
function _getDefaultSupportedChain()
955-
internal
956-
view
957-
returns (uint16 chainId)
958-
{
959-
return defaultSupportedChain;
960-
}
961-
962-
/// @notice Extract recipient address from encoded receiver data
963-
/// @param destinationChainReceiver Encoded receiver data
964-
/// @return recipient The recipient address (last 30 bytes, padded to 32 bytes)
965-
function _getRecipientAddressFromReceiver(
966-
bytes32 destinationChainReceiver
967-
) internal pure returns (bytes32 recipient) {
968-
return
969-
bytes32(
970-
uint256(destinationChainReceiver) &
971-
0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
972-
);
973-
}
974-
975846
/// @notice Validates the format of a signed quote from Wormhole Executor API
976847
/// @param signedQuote The signed quote bytes to validate
977848
/// @dev Keep validation minimal - NttManagerWithExecutor handles detailed validation

0 commit comments

Comments
 (0)