Skip to content

Commit

Permalink
Merge pull request #53 from ava-labs/add-fee-and-relayer-info-to-events
Browse files Browse the repository at this point in the history
Add fee and relayer info to events
  • Loading branch information
michaelkaplan13 authored Oct 18, 2023
2 parents a392920 + 874d6d3 commit 8457104
Show file tree
Hide file tree
Showing 14 changed files with 390 additions and 81 deletions.
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,16 @@ Next, provide the path to the `subnet-evm` repository and the path to a writeabl
```bash
./scripts/local/e2e_test.sh --local --subnet-evm ./subnet-evm --data-dir ~/tmp/e2e-test
```

### ABI Bindings

To generate Golang ABI bindings for the Solidity smart contracts, run:
```bash
./scripts/abi_go_bindings.sh
```

The auto-generated bindings should be written under the `abi-bindings/` directory.

## Docs

- [Teleporter Protocol Overview](./contracts/src/Teleporter/README.md)
Expand Down
207 changes: 186 additions & 21 deletions abi-bindings/Teleporter/TeleporterMessenger/TeleporterMessenger.go

Large diffs are not rendered by default.

18 changes: 16 additions & 2 deletions contracts/src/Teleporter/ITeleporterMessenger.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ interface ITeleporterMessenger {
event SendCrossChainMessage(
bytes32 indexed destinationChainID,
uint256 indexed messageID,
TeleporterMessage message
TeleporterMessage message,
TeleporterFeeInfo feeInfo
);

/**
Expand Down Expand Up @@ -83,9 +84,20 @@ interface ITeleporterMessenger {
event ReceiveCrossChainMessage(
bytes32 indexed originChainID,
uint256 indexed messageID,
address indexed deliverer,
address rewardRedeemer,
TeleporterMessage message
);

/**
* @dev Emitted when an account redeems accumulated relayer rewards.
*/
event RelayerRewardsRedeemed(
address indexed redeemer,
address indexed asset,
uint256 amount
);

/**
* @dev Called by transactions to initiate the sending of a cross subnet message.
*/
Expand Down Expand Up @@ -208,7 +220,9 @@ interface ITeleporterMessenger {
/**
* @dev Gets the number of receipts that have been sent to the given destination chain ID.
*/
function getReceiptQueueSize(bytes32 chainID) external view returns (uint256 size);
function getReceiptQueueSize(
bytes32 chainID
) external view returns (uint256 size);

/**
* @dev Gets the receipt at the given index in the queue for the given chain ID.
Expand Down
59 changes: 33 additions & 26 deletions contracts/src/Teleporter/TeleporterMessenger.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
// Tracks the outstanding receipts to send back to a given subnet in subsequent messages sent to it.
// Key is the subnet ID of the other subnet, and the value is a queue of pending receipts for messages
// we have received from that subnet.
mapping(bytes32 => ReceiptQueue.TeleporterMessageReceiptQueue) public outstandingReceipts;
mapping(bytes32 => ReceiptQueue.TeleporterMessageReceiptQueue)
public outstandingReceipts;

// Tracks the message hash and fee information for each message sent that we have not yet received
// a receipt for. The messages are tracked per subnet and keyed by message ID.
Expand Down Expand Up @@ -124,7 +125,8 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
requiredGasLimit: messageInput.requiredGasLimit,
allowedRelayerAddresses: messageInput.allowedRelayerAddresses,
message: messageInput.message,
receipts: outstandingReceipts[messageInput.destinationChainID].getOutstandingReceiptsToSend()
receipts: outstandingReceipts[messageInput.destinationChainID]
.getOutstandingReceiptsToSend()
});
}

Expand All @@ -142,17 +144,17 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
TeleporterMessage calldata message
) external senderNonReentrant {
// Get the previously sent message hash.
bytes32 messageHash = sentMessageInfo[destinationChainID][
message.messageID
].messageHash;
if (messageHash == bytes32(0)) {
SentMessageInfo memory existingMessageInfo = sentMessageInfo[
destinationChainID
][message.messageID];
if (existingMessageInfo.messageHash == bytes32(0)) {
// If the message hash is zero, the message was never sent.
revert MessageNotFound();
}

// Check that the hash of the provided message matches the one that was originally submitted.
bytes memory messageBytes = abi.encode(message);
if (keccak256(messageBytes) != messageHash) {
if (keccak256(messageBytes) != existingMessageInfo.messageHash) {
revert InvalidMessageHash();
}

Expand All @@ -161,7 +163,8 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
emit SendCrossChainMessage(
destinationChainID,
message.messageID,
message
message,
existingMessageInfo.feeInfo
);

// Resubmit the message to the warp message precompile now that we know the exact message was
Expand Down Expand Up @@ -346,9 +349,10 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
// Store the receipt of this message delivery. When a subsquent message is sent back
// to the origin of this message, we will clean up the receipt state.
// If the receipts queue contract for this chain doesn't exist yet, create it now.
ReceiptQueue.TeleporterMessageReceiptQueue storage receiptsQueue = outstandingReceipts[
warpMessage.sourceChainID
];
ReceiptQueue.TeleporterMessageReceiptQueue
storage receiptsQueue = outstandingReceipts[
warpMessage.sourceChainID
];

receiptsQueue.enqueue(
TeleporterMessageReceipt({
Expand All @@ -360,6 +364,8 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
emit ReceiveCrossChainMessage(
warpMessage.sourceChainID,
teleporterMessage.messageID,
msg.sender,
relayerRewardAddress,
teleporterMessage
);
}
Expand Down Expand Up @@ -491,6 +497,8 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
// reward to prevent any possible re-entrancy.
delete relayerRewardAmounts[msg.sender][feeAsset];

emit RelayerRewardsRedeemed(msg.sender, feeAsset, rewardAmount);

// We don't need to handle "fee on transfer" tokens in a special case here because
// the amount credited to the caller does not affect this contracts accounting. The
// reward is considered paid in full in all cases.
Expand Down Expand Up @@ -562,22 +570,19 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {
/**
* @dev See {ITeleporterMessenger-getReceiptQueueSize}
*/
function getReceiptQueueSize(bytes32 chainID)
external
view
returns (uint256)
{
function getReceiptQueueSize(
bytes32 chainID
) external view returns (uint256) {
return outstandingReceipts[chainID].size();
}

/**
* @dev See {ITeleporterMessenger-getReceiptAtIndex}
*/
function getReceiptAtIndex(bytes32 chainID, uint256 index)
external
view
returns (TeleporterMessageReceipt memory)
{
function getReceiptAtIndex(
bytes32 chainID,
uint256 index
) external view returns (TeleporterMessageReceipt memory) {
return outstandingReceipts[chainID].getReceiptAtIndex(index);
}

Expand Down Expand Up @@ -644,18 +649,20 @@ contract TeleporterMessenger is ITeleporterMessenger, ReentrancyGuards {

// Store the fee asset and amount to be paid to the relayer of this message upon receiving the receipt.
// Also store the message hash so that it can be retried until we get receipt of its delivery.
TeleporterFeeInfo memory adjustedFeeInfo = TeleporterFeeInfo({
contractAddress: feeInfo.contractAddress,
amount: adjustedFeeAmount
});
sentMessageInfo[destinationChainID][messageID] = SentMessageInfo({
messageHash: keccak256(teleporterMessageBytes),
feeInfo: TeleporterFeeInfo({
contractAddress: feeInfo.contractAddress,
amount: adjustedFeeAmount
})
feeInfo: adjustedFeeInfo
});

emit SendCrossChainMessage(
destinationChainID,
messageID,
teleporterMessage
teleporterMessage,
adjustedFeeInfo
);

// Submit the message to the AWM precompile.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ contract GetOutstandingReceiptsToSendTest is TeleporterMessengerTest {
hex"deadbeef"
);
expectedMessage.receipts = expectedReceipts;
TeleporterFeeInfo memory feeInfo = TeleporterFeeInfo(address(0), 0);
TeleporterMessageInput memory messageInput = TeleporterMessageInput({
destinationChainID: hex"11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff",
destinationAddress: expectedMessage.destinationAddress,
feeInfo: TeleporterFeeInfo(address(0), 0),
feeInfo: feeInfo,
requiredGasLimit: expectedMessage.requiredGasLimit,
allowedRelayerAddresses: expectedMessage.allowedRelayerAddresses,
message: expectedMessage.message
Expand All @@ -86,7 +87,8 @@ contract GetOutstandingReceiptsToSendTest is TeleporterMessengerTest {
emit SendCrossChainMessage(
messageInput.destinationChainID,
expectedMessage.messageID,
expectedMessage
expectedMessage,
feeInfo
);

// Submit the message.
Expand All @@ -113,7 +115,8 @@ contract GetOutstandingReceiptsToSendTest is TeleporterMessengerTest {
emit SendCrossChainMessage(
messageInput.destinationChainID,
nextExpectedMessage.messageID,
nextExpectedMessage
nextExpectedMessage,
feeInfo
);

// Submit the new message.
Expand Down Expand Up @@ -189,10 +192,11 @@ contract GetOutstandingReceiptsToSendTest is TeleporterMessengerTest {
hex"deadbeef"
);
expectedMessage.receipts = expectedReceiptsBatch1;
TeleporterFeeInfo memory feeInfo = TeleporterFeeInfo(address(0), 0);
TeleporterMessageInput memory messageInput = TeleporterMessageInput({
destinationChainID: hex"11223344556677889900aabbccddeeff11223344556677889900aabbccddeeff",
destinationAddress: expectedMessage.destinationAddress,
feeInfo: TeleporterFeeInfo(address(0), 0),
feeInfo: feeInfo,
requiredGasLimit: expectedMessage.requiredGasLimit,
allowedRelayerAddresses: expectedMessage.allowedRelayerAddresses,
message: expectedMessage.message
Expand All @@ -216,7 +220,8 @@ contract GetOutstandingReceiptsToSendTest is TeleporterMessengerTest {
emit SendCrossChainMessage(
messageInput.destinationChainID,
expectedMessage.messageID,
expectedMessage
expectedMessage,
feeInfo
);

// Submit the message.
Expand Down Expand Up @@ -244,7 +249,8 @@ contract GetOutstandingReceiptsToSendTest is TeleporterMessengerTest {
emit SendCrossChainMessage(
messageInput.destinationChainID,
nextExpectedMessage.messageID,
nextExpectedMessage
nextExpectedMessage,
feeInfo
);

// Submit the new message.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,14 @@ contract HandleInitialMessageExecutionTest is TeleporterMessengerTest {
_setUpSuccessGetVerifiedWarpMessageMock(0, warpMessage);

// Receive the message.
vm.expectEmit(true, true, true, true, address(teleporterMessenger));
emit ReceiveCrossChainMessage(
warpMessage.sourceChainID,
messageToReceive.messageID,
address(this),
DEFAULT_RELAYER_REWARD_ADDRESS,
messageToReceive
);
teleporterMessenger.receiveCrossChainMessage(
0,
DEFAULT_RELAYER_REWARD_ADDRESS
Expand Down Expand Up @@ -228,6 +236,14 @@ contract HandleInitialMessageExecutionTest is TeleporterMessengerTest {
messageToReceive.messageID,
messageToReceive
);
vm.expectEmit(true, true, true, true, address(teleporterMessenger));
emit ReceiveCrossChainMessage(
warpMessage.sourceChainID,
messageToReceive.messageID,
address(this),
DEFAULT_RELAYER_REWARD_ADDRESS,
messageToReceive
);
teleporterMessenger.receiveCrossChainMessage(
0,
DEFAULT_RELAYER_REWARD_ADDRESS
Expand Down Expand Up @@ -283,6 +299,14 @@ contract HandleInitialMessageExecutionTest is TeleporterMessengerTest {
messageToReceive.messageID,
messageToReceive
);
vm.expectEmit(true, true, true, true, address(teleporterMessenger));
emit ReceiveCrossChainMessage(
warpMessage.sourceChainID,
messageToReceive.messageID,
address(this),
DEFAULT_RELAYER_REWARD_ADDRESS,
messageToReceive
);
teleporterMessenger.receiveCrossChainMessage(
0,
DEFAULT_RELAYER_REWARD_ADDRESS
Expand Down
28 changes: 19 additions & 9 deletions contracts/src/Teleporter/tests/ReceiveCrossChainMessageTests.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,27 @@ contract ReceiveCrossChainMessagedTest is TeleporterMessengerTest {

// Check receipt queue size
assertEq(
teleporterMessenger.getReceiptQueueSize(
DEFAULT_ORIGIN_CHAIN_ID
),
teleporterMessenger.getReceiptQueueSize(DEFAULT_ORIGIN_CHAIN_ID),
0
);

// Receive the message.
vm.expectEmit(true, true, true, true, address(teleporterMessenger));
emit ReceiveCrossChainMessage(
warpMessage.sourceChainID,
messageToReceive.messageID,
address(this),
DEFAULT_RELAYER_REWARD_ADDRESS,
messageToReceive
);
teleporterMessenger.receiveCrossChainMessage(
0,
DEFAULT_RELAYER_REWARD_ADDRESS
);

// Check receipt queue size
assertEq(
teleporterMessenger.getReceiptQueueSize(
DEFAULT_ORIGIN_CHAIN_ID
),
teleporterMessenger.getReceiptQueueSize(DEFAULT_ORIGIN_CHAIN_ID),
1
);

Expand All @@ -83,16 +87,22 @@ contract ReceiveCrossChainMessagedTest is TeleporterMessengerTest {
_setUpSuccessGetVerifiedWarpMessageMock(3, warpMessage);

// Receive the message.
vm.expectEmit(true, true, true, true, address(teleporterMessenger));
emit ReceiveCrossChainMessage(
warpMessage.sourceChainID,
messageToReceive.messageID,
address(this),
DEFAULT_RELAYER_REWARD_ADDRESS,
messageToReceive
);
teleporterMessenger.receiveCrossChainMessage(
3,
DEFAULT_RELAYER_REWARD_ADDRESS
);

// Check receipt queue size
assertEq(
teleporterMessenger.getReceiptQueueSize(
DEFAULT_ORIGIN_CHAIN_ID
),
teleporterMessenger.getReceiptQueueSize(DEFAULT_ORIGIN_CHAIN_ID),
2
);

Expand Down
14 changes: 14 additions & 0 deletions contracts/src/Teleporter/tests/RedeemRelayerRewardsTests.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,12 @@ contract RedeemRelayerRewardsTest is TeleporterMessengerTest {
(feeRewardInfo.relayerRewardAddress, feeRewardInfo.feeAmount)
)
);
vm.expectEmit(true, true, true, true, address(teleporterMessenger));
emit RelayerRewardsRedeemed(
feeRewardInfo.relayerRewardAddress,
address(_mockFeeAsset),
feeRewardInfo.feeAmount
);
vm.prank(feeRewardInfo.relayerRewardAddress);
teleporterMessenger.redeemRelayerRewards(address(_mockFeeAsset));

Expand Down Expand Up @@ -131,6 +137,14 @@ contract RedeemRelayerRewardsTest is TeleporterMessengerTest {

// Receive the mock message.
address expectedRelayerRewardAddress = 0x93753a9eA4C9D6eeed9f64eA92E97ce1f5FBAeDe;
vm.expectEmit(true, true, true, true, address(teleporterMessenger));
emit ReceiveCrossChainMessage(
warpMessage.sourceChainID,
messageToReceive.messageID,
address(this),
expectedRelayerRewardAddress,
messageToReceive
);
teleporterMessenger.receiveCrossChainMessage(
0,
expectedRelayerRewardAddress
Expand Down
Loading

0 comments on commit 8457104

Please sign in to comment.