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

Arb l1 to l2 hook and ISM #3106

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open

Conversation

exp7l
Copy link

@exp7l exp7l commented Dec 28, 2023

Description

fixes #2845:

  • This implements a hook that calls (L1) Arbitrum's Inbox's createRetryableTicket and provides a quoting method for message ID dispatching.

  • This also implements an ISM that mostly follows OPStackISM. Specifically, provided the ISM is the message originator (i.e. the address that creates the Retryable ticket on L1), ISM escrows any ETH sent and verifies provided message ID. When relayer relays the message later, the escrowed ETH is released and message is relayed to recipient.

  • Implementation includes deploy scripts for deploying to testnet or any network if you edit the network settings.

Testing

Copy link

changeset-bot bot commented Dec 28, 2023

⚠️ No Changeset found

Latest commit: 2d9f3ae

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@exp7l exp7l marked this pull request as ready for review December 29, 2023 05:17
@exp7l exp7l changed the title Arb l1 to l2 Arb l1 to l2 hook and ISM Dec 29, 2023
Comment on lines 39 to 62
function _dispatch() private {
vm.createSelectFork("sepolia");
vm.startBroadcast(sk);
bytes memory metadata = StandardHookMetadata.formatMetadata(
TEST_MSG_VALUE,
GAS_LIMIT,
sender,
abi.encodePacked(MAX_FEE_PER_GAS)
);
uint256 deposit = ArbitrumOrbitHook(ARBHOOK).quoteDispatch(
metadata,
TEST_MESSAGE
);
IMailbox(MAILBOX).dispatch{
value: deposit + MAX_FEE_PER_GAS * GAS_LIMIT
}(
ARBITRUM_DOMAIN,
TypeCasts.addressToBytes32(address(testRecipient)),
TEST_MESSAGE,
metadata,
ArbitrumOrbitHook(ARBHOOK)
);
vm.stopBroadcast();
}
Comment on lines 39 to 62
function _dispatch() private {
vm.createSelectFork("sepolia");
vm.startBroadcast(sk);
bytes memory metadata = StandardHookMetadata.formatMetadata(
TEST_MSG_VALUE,
GAS_LIMIT,
sender,
abi.encodePacked(MAX_FEE_PER_GAS)
);
uint256 deposit = ArbitrumOrbitHook(ARBHOOK).quoteDispatch(
metadata,
TEST_MESSAGE
);
IMailbox(MAILBOX).dispatch{
value: deposit + MAX_FEE_PER_GAS * GAS_LIMIT
}(
ARBITRUM_DOMAIN,
TypeCasts.addressToBytes32(address(testRecipient)),
TEST_MESSAGE,
metadata,
ArbitrumOrbitHook(ARBHOOK)
);
vm.stopBroadcast();
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines 9 to 15
function run() external {
vm.createSelectFork("sepolia_arb");
string memory seed = vm.envString("SEEDPHRASE");
vm.startBroadcast(vm.deriveKey(seed, 0));
new ArbitrumOrbitIsm();
vm.stopBroadcast();
}

Check warning

Code scanning / Slither

Unused return Medium

Comment on lines 64 to 73
function run() external {
vm.createSelectFork("sepolia_arb");
vm.startBroadcast(sk);
testRecipient = new TestRecipient();
ArbitrumOrbitIsm(ARBISM).setAuthorizedHook(
TypeCasts.addressToBytes32(ARBHOOK)
);
vm.stopBroadcast();
_dispatch();
}

Check warning

Code scanning / Slither

Unused return Medium

solidity/contracts/script/ArbitrumL1Deployer.s.sol Dismissed Show dismissed Hide dismissed
solidity/contracts/hooks/ArbitrumOrbitHook.sol Dismissed Show dismissed Hide dismissed
solidity/contracts/script/ArbitrumDispatcher.s.sol Dismissed Show dismissed Hide dismissed
solidity/contracts/script/ArbitrumDispatcher.s.sol Dismissed Show dismissed Hide dismissed
solidity/contracts/script/ArbitrumDispatcher.s.sol Dismissed Show dismissed Hide dismissed
solidity/contracts/script/ArbitrumDispatcher.s.sol Dismissed Show dismissed Hide dismissed
Copy link
Member

@yorhodes yorhodes left a comment

Choose a reason for hiding this comment

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

great start! I like how you reused the existing abstractions

solidity/test/isms/ArbitrumOrbitIsm.t.sol Show resolved Hide resolved
* [2:34] msg.value
* [34:66] Gas limit for message
* [66:86] Refund address for message
* [86:117] Max fee per gas (custom)
Copy link
Member

Choose a reason for hiding this comment

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

it would be good to have a default here otherwise this is quite a breaking change for developers

Copy link
Author

Choose a reason for hiding this comment

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

See comment below.

Comment on lines 75 to 83
require(
metadata.msgValue(0) < 2 ** 255,
"ArbitrumOrbitHook: msgValue must be less than 2 ** 255"
);
// To make sure the default value for each meta datum IS NOT used.
require(
metadata.length >= MIN_METADATA_LENGTH,
"ArbitrumOrbitHook: invalid metadata length"
);
Copy link
Member

Choose a reason for hiding this comment

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

I wonder if we should just move these checks into the AbstractMessageIdAuthHook

Copy link
Author

Choose a reason for hiding this comment

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

  1. Agreed, moved msg value check into AbstractMessageIdAuthHook and changed the OPStackhook as a drive-by change.
  2. To make UX better, I made max fee per gas an optional metadata, defaulted to use IGP's gas price (like you suggested below) unless user provides max fee per gas through metadata. So the length check shouldn't be needed anymore.

uint256 ticketID = baseInbox.createRetryableTicket{value: msg.value}(
TypeCasts.bytes32ToAddress(ism),
metadata.msgValue(0),
baseInbox.calculateRetryableSubmissionFee(PAYLOAD_LENGTH, 0),
Copy link
Member

Choose a reason for hiding this comment

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

should PAYLOAD_LENGTH actually be derived from message.length?

Copy link
Member

Choose a reason for hiding this comment

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

and can we dedupe this with quoteDispatch somehow

Copy link
Author

Choose a reason for hiding this comment

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

  1. Ah if I understand correctly, PAYLOAD_LENGTH is always 36 bytes because the payload is the verifyMessageId call to the ISM: the calldata has 4 bytes for method ID and 32 bytes for message ID.
  2. Deduped, please take a look.

Comment on lines 103 to 106
uint256 maxFeePerGas = abi.decode(
metadata.getCustomMetadata(),
(uint256)
);
Copy link
Member

Choose a reason for hiding this comment

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

the InterchainGasPaymaster has oracleized gas prices which maybe could be reused here, or added to the "standard metadata" shape

Copy link
Author

Choose a reason for hiding this comment

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

See above.

@avious00
Copy link
Contributor

hey @exp7l - as Yorke shared, this is a great start on a much needed hook. Are you stuck on anything? How can we help?

@exp7l
Copy link
Author

exp7l commented Jan 29, 2024

@avious00 my apologies, I'm moving these few weeks and got distracted. I should be able to come back to this pr in the coming week. Thanks for the patience.

@yorhodes
Copy link
Member

yorhodes commented Feb 1, 2024

@avious00 my apologies, I'm moving these few weeks and got distracted. I should be able to come back to this pr in the coming week. Thanks for the patience.

Any updates here?

@exp7l
Copy link
Author

exp7l commented Feb 1, 2024

@avious00 my apologies, I'm moving these few weeks and got distracted. I should be able to come back to this pr in the coming week. Thanks for the patience.

Any updates here?

looking now

@exp7l
Copy link
Author

exp7l commented Feb 2, 2024

Added some changes and comments above, what do you think? @yorhodes

@exp7l
Copy link
Author

exp7l commented Feb 8, 2024

@yorhodes @avious00 hi any updates?

@yorhodes yorhodes self-requested a review February 15, 2024 21:35
Copy link
Member

@yorhodes yorhodes left a comment

Choose a reason for hiding this comment

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

almost there, nice work!

solidity/contracts/isms/hook/ArbitrumOrbitIsm.sol Outdated Show resolved Hide resolved
solidity/contracts/hooks/ArbitrumOrbitHook.sol Outdated Show resolved Hide resolved
solidity/contracts/script/ArbitrumDispatcher.s.sol Outdated Show resolved Hide resolved
solidity/contracts/script/ArbitrumL1Deployer.s.sol Outdated Show resolved Hide resolved
solidity/contracts/script/ArbitrumL2Deployer.s.sol Outdated Show resolved Hide resolved
@avious00
Copy link
Contributor

hey @exp7l you're pretty close - would be great to push this over the line since a lot of people have been asking

This reverts commit 5381ff9 due to misconfigured yarn.lock
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

Arbitrum/Orbit L1 => L2 Hook and ISM
4 participants