Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Let USDC look for the exact nonce instead of relying on ordering #1025

Draft
wants to merge 3 commits into
base: ccip-develop
Choose a base branch
from

Conversation

RensR
Copy link
Collaborator

@RensR RensR commented Jun 14, 2024

Motivation

We don't want to have the offchain code be reliant on onchain ordering of events.

Solution

Since we only relied on the ordering of USDC events, we can solve the dependency by removing the ordering requirement for USDC. With this new method we look for the exact nonce, which is significantly less brittle overal. It should not care about log ordering, so we can remove the comment from the onRamps

Copy link
Contributor

github-actions bot commented Jun 14, 2024

LCOV of commit da1ba26 during Solidity Foundry #5441

Summary coverage rate:
  lines......: 98.9% (1478 of 1495 lines)
  functions..: 95.8% (297 of 310 functions)
  branches...: 93.1% (639 of 686 branches)

Files changed coverage rate: n/a

// fetch all the usdc logs for the provided tx hash
logs, err := u.lp.IndexedLogsByTxHash(
func (u *USDCReaderImpl) GetUSDCMessageWithNonce(ctx context.Context, nonce [32]byte) ([]byte, error) {
logs, err := u.lp.IndexedLogsTopicRange(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm not sure I follow this - we want this event https://github.com/circlefin/evm-cctp-contracts/blob/master/src/MessageTransmitter.sol#L41 (MessageSent not MessageReceived)?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR doesn't change the event we're looking for, it's still u.usdcMessageSent which is eventSig := utils.Keccak256Fixed([]byte("MessageSent(bytes)"))

Copy link
Collaborator Author

@RensR RensR Jun 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahhh I see what you're saying. I was looking at

event DepositForBurn(
  uint64 indexed nonce,
  address indexed burnToken,
  uint256 amount,
  address indexed depositor,
  bytes32 mintRecipient,
  uint32 destinationDomain,
  bytes32 destinationTokenMessenger,
  bytes32 destinationCaller
);

Which is the USDC msg but not the CCTP msg, which is


 event MessageSent(bytes message);

uint32 _msgVersion,
uint32 _msgSourceDomain,
uint32 _msgDestinationDomain,
uint64 _msgNonce,
bytes32 _msgSender,
bytes32 _msgRecipient,
bytes32 _msgDestinationCaller,
bytes memory _msgRawBody

 emit MessageSent(abi.encodePacked(
        _msgVersion,
        _msgSourceDomain,
        _msgDestinationDomain,
        _msgNonce,
        _msgSender,
        _msgRecipient,
        _msgDestinationCaller,
        _msgRawBody
    );
);

Copy link
Collaborator Author

@RensR RensR Jun 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like we can still construct the query for this log though, as the first 5 elements should all be known, so we could construct the query for the first slot using those. For EVM (the only supported networks for USDC anyway) you don't even have to know the msg sender, as it will always be a 160 bit EVM address which adds only 0x000.... to the first slot

_msgVersion is always 0
_msgSourceDomain is known
_msgDestinationDomain is known
_msgNonce is known
_msgSender is known (the pool)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah seems possible, not the most straightforward thing though. I think you'd have to account for the offset/length slots of the bytes encoding as well so it'd be 3 words and the length would include the burn message body length, which looks like its static as well (luckily). Also would need to read the dest domain and pool address from the chain to smoothly support adding new dest domains/pool upgrades. I think worth a little exploratory doc/discussion though

Copy link
Collaborator Author

@RensR RensR Jun 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would only have to query for the third slot, which contains the items I mentioned above.

MessageSent
[topic0] 0x8c5261668696ce22758910d05bab8f186d6eb247ceac2af2e82c7dc17669b036
 0000000000000000000000000000000000000000000000000000000000000020
 00000000000000000000000000000000000000000000000000000000000000f8
 0000000000000000000000020000000000011c30000000000000000000000000
.....

This is a real MessageSent event emitted on mainnet. As you can see, we'd be interested in the last slot I copied here. Afaik the logPoller simply treats each slot as a queryable object.

0000000000000000000000020000000000011c30000000000000000000000000
=>
00000000 00000000 00000002 0000000000011c30 000000000000000000000000
version  srcDom   dstDom   nonce            start of sender (evm, so always 000...)

ctx,
u.usdcMessageSent,
u.transmitterAddress,
common.HexToHash(txHash),
USDC_MESSAGE_NONCE_INDEX,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we getting the topicIndex 3? Shouldn't we have only 1 topic considering that the event doesn't emit indexed value?

event MessageSent(bytes message);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expect if topicIndex in logpoller actually means slots. Then, I understand that we need to get the 3rd slot (0: event signature, 1: offset to data, 2: length of data, 3: packed data).

nonceBytes := [8]byte{}
binary.BigEndian.PutUint64(nonceBytes[:], nonce)

senderBytes := [12]byte{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The sender address is the pool address. We probably need to have it as an input param (like sourceDomain and destDomain)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can get the sourceDomain from the MessageTransmitter https://github.com/circlefin/evm-cctp-contracts/blob/master/src/MessageTransmitter.sol#L72. This means we probably need to add method in usdc_reader.

nonceBytes := [8]byte{}
binary.BigEndian.PutUint64(nonceBytes[:], nonce)

senderBytes := [12]byte{}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can get the sourceDomain from the MessageTransmitter https://github.com/circlefin/evm-cctp-contracts/blob/master/src/MessageTransmitter.sol#L72. This means we probably need to add method in usdc_reader.

@@ -119,6 +141,8 @@ func NewUSDCReader(lggr logger.Logger, jobID string, transmitter common.Address,
Retention: CommitExecLogsRetention,
},
transmitterAddress: transmitter,
sourceDomain: 0, // TODO
destDomain: 1, // TODO
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the destDomain, it cannot be fetched from the source MessageTransmitter contract. I wonder if we can add the MessageTransmitter destination contract address in the config too and call the the domain

Copy link
Contributor

This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.

@github-actions github-actions bot added the Stale label Sep 14, 2024
@RensR RensR removed the Stale label Sep 16, 2024
Copy link
Contributor

github-actions bot commented Nov 1, 2024

This PR is stale because it has been open 45 days with no activity. Remove stale label or comment or this will be closed in 10 days.

@github-actions github-actions bot added the Stale label Nov 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants