Skip to content

Commit 966ad00

Browse files
committed
evm: Per chain transceivers
1 parent 8b8adc9 commit 966ad00

18 files changed

+1817
-276
lines changed

evm/script/helpers/DeployWormholeNttBase.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ contract DeployWormholeNttBase is ParseNttConfig {
100100
}
101101

102102
// Hardcoded to one since these scripts handle Wormhole-only deployments.
103-
INttManager(nttManager).setThreshold(1);
103+
// TODO: We need the sourceChainId to set the threshold. Also need to enable sending and receiving.
104+
// INttManager(nttManager).setThreshold(1);
104105
console2.log("Threshold set on NttManager: %d", uint256(1));
105106
}
106107

evm/src/NttManager/ManagerBase.sol

Lines changed: 23 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ abstract contract ManagerBase is
5252
}
5353

5454
function _migrate() internal virtual override {
55-
_checkThresholdInvariants();
5655
_checkTransceiversInvariants();
5756
}
5857

@@ -68,13 +67,6 @@ abstract contract ManagerBase is
6867

6968
// =============== Storage Getters/Setters ==============================================
7069

71-
function _getThresholdStorage() private pure returns (_Threshold storage $) {
72-
uint256 slot = uint256(THRESHOLD_SLOT);
73-
assembly ("memory-safe") {
74-
$.slot := slot
75-
}
76-
}
77-
7870
function _getMessageAttestationsStorage()
7971
internal
8072
pure
@@ -139,15 +131,19 @@ abstract contract ManagerBase is
139131
bytes32 nttManagerMessageHash =
140132
TransceiverStructs.nttManagerMessageDigest(sourceChainId, payload);
141133

134+
// The `msg.sender` is the transceiver. Get the index for it.
135+
uint8 index = _getTransceiverInfosStorage()[msg.sender].index;
136+
137+
// TODO: Is there a race condition with disabling a transceiver while a tx is outstanding?
138+
if (!_isRecvTransceiverEnabledForChain(sourceChainId, index)) {
139+
revert CallerNotTransceiver(msg.sender);
140+
}
141+
142142
// set the attested flag for this transceiver.
143143
// NOTE: Attestation is idempotent (bitwise or 1), but we revert
144144
// anyway to ensure that the client does not continue to initiate calls
145145
// to receive the same message through the same transceiver.
146-
if (
147-
transceiverAttestedToMessage(
148-
nttManagerMessageHash, _getTransceiverInfosStorage()[msg.sender].index
149-
)
150-
) {
146+
if (transceiverAttestedToMessage(nttManagerMessageHash, index)) {
151147
revert TransceiverAlreadyAttestedToMessage(nttManagerMessageHash);
152148
}
153149
_setTransceiverAttestedToMessage(nttManagerMessageHash, msg.sender);
@@ -162,7 +158,7 @@ abstract contract ManagerBase is
162158
) internal returns (bytes32, bool) {
163159
bytes32 digest = TransceiverStructs.nttManagerMessageDigest(sourceChainId, message);
164160

165-
if (!isMessageApproved(digest)) {
161+
if (!isMessageApproved(sourceChainId, digest)) {
166162
revert MessageNotApproved(digest);
167163
}
168164

@@ -225,7 +221,7 @@ abstract contract ManagerBase is
225221
)
226222
{
227223
// cache enabled transceivers to avoid multiple storage reads
228-
address[] memory enabledTransceivers = _getEnabledTransceiversStorage();
224+
address[] memory enabledTransceivers = getEnabledSendTransceiversForChain(recipientChain);
229225

230226
TransceiverStructs.TransceiverInstruction[] memory instructions;
231227

@@ -280,15 +276,16 @@ abstract contract ManagerBase is
280276
}
281277

282278
/// @inheritdoc IManagerBase
283-
function getThreshold() public view returns (uint8) {
284-
return _getThresholdStorage().num;
279+
/// @dev This is here because it is defined in IManagerBase.
280+
function getThreshold(
281+
uint16 sourceChainId
282+
) public view returns (uint8) {
283+
return _getPerChainRecvTransceiverDataStorage()[sourceChainId].threshold;
285284
}
286285

287286
/// @inheritdoc IManagerBase
288-
function isMessageApproved(
289-
bytes32 digest
290-
) public view returns (bool) {
291-
uint8 threshold = getThreshold();
287+
function isMessageApproved(uint16 sourceChainId, bytes32 digest) public view returns (bool) {
288+
uint8 threshold = getThreshold(sourceChainId);
292289
return messageAttestations(digest) >= threshold && threshold > 0;
293290
}
294291

@@ -354,63 +351,21 @@ abstract contract ManagerBase is
354351
address transceiver
355352
) external onlyOwner {
356353
_setTransceiver(transceiver);
357-
358-
_Threshold storage _threshold = _getThresholdStorage();
359-
// We do not automatically increase the threshold here.
360-
// Automatically increasing the threshold can result in a scenario
361-
// where in-flight messages can't be redeemed.
362-
// For example: Assume there is 1 Transceiver and the threshold is 1.
363-
// If we were to add a new Transceiver, the threshold would increase to 2.
364-
// However, all messages that are either in-flight or that are sent on
365-
// a source chain that does not yet have 2 Transceivers will only have been
366-
// sent from a single transceiver, so they would never be able to get
367-
// redeemed.
368-
// Instead, we leave it up to the owner to manually update the threshold
369-
// after some period of time, ideally once all chains have the new Transceiver
370-
// and transfers that were sent via the old configuration are all complete.
371-
// However if the threshold is 0 (the initial case) we do increment to 1.
372-
if (_threshold.num == 0) {
373-
_threshold.num = 1;
374-
}
375-
376-
emit TransceiverAdded(transceiver, _getNumTransceiversStorage().enabled, _threshold.num);
377-
378-
_checkThresholdInvariants();
354+
emit TransceiverAdded(transceiver, _getNumTransceiversStorage().enabled);
379355
}
380356

381357
/// @inheritdoc IManagerBase
382358
function removeTransceiver(
383359
address transceiver
384360
) external onlyOwner {
385361
_removeTransceiver(transceiver);
386-
387-
_Threshold storage _threshold = _getThresholdStorage();
388-
uint8 numEnabledTransceivers = _getNumTransceiversStorage().enabled;
389-
390-
if (numEnabledTransceivers < _threshold.num) {
391-
_threshold.num = numEnabledTransceivers;
392-
}
393-
394-
emit TransceiverRemoved(transceiver, _threshold.num);
395-
396-
_checkThresholdInvariants();
362+
emit TransceiverRemoved(transceiver);
397363
}
398364

399365
/// @inheritdoc IManagerBase
400-
function setThreshold(
401-
uint8 threshold
402-
) external onlyOwner {
403-
if (threshold == 0) {
404-
revert ZeroThreshold();
405-
}
406-
407-
_Threshold storage _threshold = _getThresholdStorage();
408-
uint8 oldThreshold = _threshold.num;
409-
410-
_threshold.num = threshold;
411-
_checkThresholdInvariants();
412-
413-
emit ThresholdChanged(oldThreshold, threshold);
366+
/// @dev This is here because it is defined in IManagerBase.
367+
function setThreshold(uint16 sourceChainId, uint8 threshold) external onlyOwner {
368+
_setThreshold(sourceChainId, threshold);
414369
}
415370

416371
// =============== Internal ==============================================================
@@ -480,20 +435,4 @@ abstract contract ManagerBase is
480435
);
481436
}
482437
}
483-
484-
function _checkThresholdInvariants() internal view {
485-
uint8 threshold = _getThresholdStorage().num;
486-
_NumTransceivers memory numTransceivers = _getNumTransceiversStorage();
487-
488-
// invariant: threshold <= enabledTransceivers.length
489-
if (threshold > numTransceivers.enabled) {
490-
revert ThresholdTooHigh(threshold, numTransceivers.enabled);
491-
}
492-
493-
if (numTransceivers.registered > 0) {
494-
if (threshold == 0) {
495-
revert ZeroThreshold();
496-
}
497-
}
498-
}
499438
}

evm/src/NttManager/NttManager.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
6868

6969
function _initialize() internal virtual override {
7070
__NttManager_init();
71-
_checkThresholdInvariants();
7271
_checkTransceiversInvariants();
7372
}
7473

@@ -192,7 +191,7 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
192191
// Compute manager message digest and record transceiver attestation.
193192
bytes32 nttManagerMessageHash = _recordTransceiverAttestation(sourceChainId, payload);
194193

195-
if (isMessageApproved(nttManagerMessageHash)) {
194+
if (isMessageApproved(sourceChainId, nttManagerMessageHash)) {
196195
executeMsg(sourceChainId, sourceNttManagerAddress, payload);
197196
}
198197
}

0 commit comments

Comments
 (0)