Skip to content
Open
5 changes: 3 additions & 2 deletions evm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,10 @@ _Events_
/// @notice Emitted when a transfer has been redeemed
/// (either minted or unlocked on the recipient chain).
/// @dev Topic0
/// 0x504e6efe18ab9eed10dc6501a417f5b12a2f7f2b1593aed9b89f9bce3cf29a91.
/// 0x822760cb8aef838664db98515460929d89d5799b7546e9269dffdc09e2cbb995.
/// @param sourceChain The source chain.
/// @param digest The digest of the message.
event TransferRedeemed(bytes32 indexed digest);
event TransferRedeemed(uint16 indexed sourceChain, bytes32 indexed digest);
```

## Prerequisites
Expand Down
2 changes: 1 addition & 1 deletion evm/src/NttManager/ManagerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ abstract contract ManagerBase is
_setTransceiverAttestedToMessage(digest, _getTransceiverInfosStorage()[transceiver].index);

emit MessageAttestedTo(
digest, transceiver, _getTransceiverInfosStorage()[transceiver].index
chainId, digest, transceiver, _getTransceiverInfosStorage()[transceiver].index
);
}

Expand Down
24 changes: 19 additions & 5 deletions evm/src/NttManager/NttManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,9 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
sourceChainId, sourceNttManagerAddress, message.id, message.sender, nativeTokenTransfer
);

_mintOrUnlockToRecipient(digest, transferRecipient, nativeTransferAmount, false);
_mintOrUnlockToRecipient(
sourceChainId, digest, transferRecipient, nativeTransferAmount, false
);
}

/// @dev Override this function to process an additional payload on the NativeTokenTransfer
Expand Down Expand Up @@ -284,7 +286,7 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
bool isRateLimited = _isInboundAmountRateLimited(nativeTransferAmount, sourceChainId);
if (isRateLimited) {
// queue up the transfer
_enqueueInboundTransfer(digest, nativeTransferAmount, transferRecipient);
_enqueueInboundTransfer(sourceChainId, digest, nativeTransferAmount, transferRecipient);

// end execution early
return true;
Expand Down Expand Up @@ -317,7 +319,13 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
delete _getInboundQueueStorage()[digest];

// run it through the mint/unlock logic
_mintOrUnlockToRecipient(digest, queuedTransfer.recipient, queuedTransfer.amount, false);
_mintOrUnlockToRecipient(
queuedTransfer.sourceChain,
digest,
queuedTransfer.recipient,
queuedTransfer.amount,
false
);
}

/// @inheritdoc INttManager
Expand Down Expand Up @@ -370,7 +378,11 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {

// return the queued funds to the sender
_mintOrUnlockToRecipient(
bytes32(uint256(messageSequence)), msg.sender, queuedTransfer.amount, true
queuedTransfer.sourceChain,
bytes32(uint256(messageSequence)),
msg.sender,
queuedTransfer.amount,
true
);
}

Expand Down Expand Up @@ -494,6 +506,7 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {

// queue up and return
_enqueueOutboundTransfer(
chainId,
sequence,
trimmedAmount,
recipientChain,
Expand Down Expand Up @@ -611,6 +624,7 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
}

function _mintOrUnlockToRecipient(
uint16 sourceChain,
bytes32 digest,
address recipient,
TrimmedAmount amount,
Expand All @@ -626,7 +640,7 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
if (cancelled) {
emit OutboundTransferCancelled(uint256(digest), recipient, untrimmedAmount);
} else {
emit TransferRedeemed(digest);
emit TransferRedeemed(sourceChain, digest);
}

if (mode == Mode.LOCKING) {
Expand Down
7 changes: 5 additions & 2 deletions evm/src/interfaces/IManagerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,14 @@ interface IManagerBase {

/// @notice Emitted when a message has been attested to.
/// @dev Topic0
/// 0x35a2101eaac94b493e0dfca061f9a7f087913fde8678e7cde0aca9897edba0e5.
/// 0xf1ec44311dd9bf51a389c38e415716ad070edf9e303ea55ed7ae11472a5f031d.
/// @param sourceChain The source chain.
/// @param digest The digest of the message.
/// @param transceiver The address of the transceiver.
/// @param index The index of the transceiver in the bitmap.
event MessageAttestedTo(bytes32 digest, address transceiver, uint8 index);
event MessageAttestedTo(
uint16 indexed sourceChain, bytes32 digest, address transceiver, uint8 index
);

/// @notice Emmitted when the threshold required transceivers is changed.
/// @dev Topic0
Expand Down
5 changes: 3 additions & 2 deletions evm/src/interfaces/INttManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ interface INttManager is IManagerBase {
/// @notice Emitted when a transfer has been redeemed
/// (either minted or unlocked on the recipient chain).
/// @dev Topic0
/// 0x504e6efe18ab9eed10dc6501a417f5b12a2f7f2b1593aed9b89f9bce3cf29a91.
/// 0x822760cb8aef838664db98515460929d89d5799b7546e9269dffdc09e2cbb995.
/// @param sourceChain The source chain.
/// @param digest The digest of the message.
event TransferRedeemed(bytes32 indexed digest);
event TransferRedeemed(uint16 indexed sourceChain, bytes32 indexed digest);

/// @notice Emitted when an outbound transfer has been cancelled
/// @dev Topic0
Expand Down
4 changes: 4 additions & 0 deletions evm/src/interfaces/IRateLimiter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,15 @@ interface IRateLimiter {

/// @notice Parameters for an outbound queued transfer.
/// @dev
/// - sourceChain: the chain of the sender.
/// - recipient: the recipient of the transfer.
/// - amount: the amount of the transfer, trimmed.
/// - txTimestamp: the timestamp of the transfer.
/// - recipientChain: the chain of the recipient.
/// - sender: the sender of the transfer.
/// - transceiverInstructions: additional instructions to be forwarded to the recipient chain.
struct OutboundQueuedTransfer {
uint16 sourceChain;
bytes32 recipient;
bytes32 refundAddress;
TrimmedAmount amount;
Expand All @@ -75,10 +77,12 @@ interface IRateLimiter {

/// @notice Parameters for an inbound queued transfer.
/// @dev
/// - sourceChain: the chain of the sender.
/// - amount: the amount of the transfer, trimmed.
/// - txTimestamp: the timestamp of the transfer.
/// - recipient: the recipient of the transfer.
struct InboundQueuedTransfer {
uint16 sourceChain;
TrimmedAmount amount;
uint64 txTimestamp;
address recipient;
Expand Down
4 changes: 4 additions & 0 deletions evm/src/libraries/RateLimiter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ abstract contract RateLimiter is IRateLimiter, IRateLimiterEvents {
}

function _enqueueOutboundTransfer(
uint16 sourceChain,
uint64 sequence,
TrimmedAmount amount,
uint16 recipientChain,
Expand All @@ -305,6 +306,7 @@ abstract contract RateLimiter is IRateLimiter, IRateLimiterEvents {
bytes memory transceiverInstructions
) internal {
_getOutboundQueueStorage()[sequence] = OutboundQueuedTransfer({
sourceChain: sourceChain,
amount: amount,
recipientChain: recipientChain,
recipient: recipient,
Expand All @@ -318,11 +320,13 @@ abstract contract RateLimiter is IRateLimiter, IRateLimiterEvents {
}

function _enqueueInboundTransfer(
uint16 sourceChain,
bytes32 digest,
TrimmedAmount amount,
address recipient
) internal {
_getInboundQueueStorage()[digest] = InboundQueuedTransfer({
sourceChain: sourceChain,
amount: amount,
recipient: recipient,
txTimestamp: uint64(block.timestamp)
Expand Down
16 changes: 11 additions & 5 deletions evm/test/IntegrationStandalone.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ contract TestEndToEndBase is Test, IRateLimiterEvents {

vm.stopPrank();

// Get the TransferSent(bytes32) event to ensure it matches up with the TransferRedeemed(bytes32) event later
// Get the TransferSent(bytes32) event digest to ensure it matches up with the TransferRedeemed(uint16,bytes32) event digest later
Vm.Log[] memory recordedLogs = vm.getRecordedLogs();
bytes32 sentEventDigest;
for (uint256 i = 0; i < recordedLogs.length; i++) {
Expand Down Expand Up @@ -220,18 +220,24 @@ contract TestEndToEndBase is Test, IRateLimiterEvents {
);
}

// Get the TransferRedeemed(bytes32) event to ensure it matches up with the TransferSent(bytes32) event earlier
// Get the TransferRedeemed(uint16,bytes32) event digest to ensure it matches up with the TransferSent(bytes32) event digest earlier
recordedLogs = vm.getRecordedLogs();
bytes32 recvEventDigest;
bytes32 recvSourceChain;
for (uint256 i = 0; i < recordedLogs.length; i++) {
if (recordedLogs[i].topics[0] == keccak256("TransferRedeemed(bytes32)")) {
recvEventDigest = recordedLogs[i].topics[1];
if (recordedLogs[i].topics[0] == keccak256("TransferRedeemed(uint16,bytes32)")) {
recvSourceChain = recordedLogs[i].topics[1];
recvEventDigest = recordedLogs[i].topics[2];
break;
}
}
require(
recvSourceChain == bytes32(uint256(chainId1)),
"Incorrect TransferRedeemed(uint16,bytes32) event sourceChain"
);
require(
sentEventDigest == recvEventDigest,
"TransferRedeemed(bytes32) event should match TransferSent(bytes32)"
"TransferRedeemed(uint16,bytes32) event digest should match TransferSent(bytes32) event digest"
);

// Can't resubmit the same message twice
Expand Down
Loading