Skip to content

Commit

Permalink
adds gas estimation fix to scroll validator
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-de-leon-cll committed Feb 20, 2024
1 parent b9952f9 commit 0aa68b2
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 6 deletions.
8 changes: 4 additions & 4 deletions contracts/gas-snapshots/l2ep.gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ ScrollSequencerUptimeFeed_UpdateStatus:test_RevertIfNotL2CrossDomainMessengerAdd
ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenNoChange() (gas: 72782)
ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndNoTimeChange() (gas: 92993)
ScrollSequencerUptimeFeed_UpdateStatus:test_UpdateStatusWhenStatusChangeAndTimeChange() (gas: 93053)
ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 15503)
ScrollValidator_Validate:test_PostSequencerOffline() (gas: 75094)
ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 75156)
ScrollValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15563)
ScrollValidator_SetGasLimit:test_CorrectlyUpdatesTheGasLimit() (gas: 15637)
ScrollValidator_Validate:test_PostSequencerOffline() (gas: 78367)
ScrollValidator_Validate:test_PostSequencerStatusWhenThereIsNotStatusChange() (gas: 78423)
ScrollValidator_Validate:test_RevertsIfCalledByAnAccountWithNoAccess() (gas: 15569)
21 changes: 19 additions & 2 deletions contracts/src/v0.8/l2ep/dev/scroll/ScrollValidator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,35 @@ pragma solidity 0.8.19;
import {SequencerUptimeFeed} from "../SequencerUptimeFeed.sol";
import {GasLimitValidator} from "../GasLimitValidator.sol";

import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol";
import {IL1ScrollMessenger} from "@scroll-tech/contracts/L1/IL1ScrollMessenger.sol";

/// @title ScrollValidator - makes cross chain call to update the Sequencer Uptime Feed on L2
contract ScrollValidator is GasLimitValidator {
string public constant override typeAndVersion = "ScrollValidator 1.0.0";

// solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i
address public immutable L1_MSG_QUEUE_ADDR;

/// @param l1CrossDomainMessengerAddress address the L1CrossDomainMessenger contract address
/// @param l2UptimeFeedAddr the address of the SequencerUptimeFeed contract address
/// @param gasLimit the gasLimit to use for sending a message from L1 to L2
constructor(
address l1CrossDomainMessengerAddress,
address l2UptimeFeedAddr,
address l1MessageQueueAddr,
uint32 gasLimit
) GasLimitValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) {}
) GasLimitValidator(l1CrossDomainMessengerAddress, l2UptimeFeedAddr, gasLimit) {
// solhint-disable-next-line custom-errors
require(l1MessageQueueAddr != address(0), "Invalid L1 message queue address");
L1_MSG_QUEUE_ADDR = l1MessageQueueAddr;
}

/// @notice makes this contract payable
/// @dev receives funds:
/// - to use them (if configured) to pay for L2 execution on L1
/// - when withdrawing funds from L2 xDomain alias address (pay for L2 execution on L2)
receive() external payable {}

/// @notice validate method sends an xDomain L2 tx to update Uptime Feed contract on L2.
/// @dev A message is sent using the L1CrossDomainMessenger. This method is accessed controlled.
Expand All @@ -29,7 +44,9 @@ contract ScrollValidator is GasLimitValidator {
int256 currentAnswer
) external override checkAccess returns (bool) {
// Make the xDomain call
IL1ScrollMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage(
IL1ScrollMessenger(L1_CROSS_DOMAIN_MESSENGER_ADDRESS).sendMessage{
value: IL1MessageQueue(L1_MSG_QUEUE_ADDR).estimateCrossDomainMessageFee(s_gasLimit)
}(
L2_UPTIME_FEED_ADDR,
0,
abi.encodeWithSelector(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {IL1MessageQueue} from "@scroll-tech/contracts/L1/rollup/IL1MessageQueue.sol";

contract MockScrollL1MessageQueue is IL1MessageQueue {
/// @notice The start index of all pending inclusion messages.
function pendingQueueIndex() external pure returns (uint256) {
return 0;
}

/// @notice Return the index of next appended message.
function nextCrossDomainMessageIndex() external pure returns (uint256) {
return 0;
}

/// @notice Return the message of in `queueIndex`.
function getCrossDomainMessage(uint256 /* queueIndex */) external pure returns (bytes32) {
return "";
}

/// @notice Return the amount of ETH should pay for cross domain message.
function estimateCrossDomainMessageFee(uint256 /* gasLimit */) external pure returns (uint256) {
return 0;
}

/// @notice Return the amount of intrinsic gas fee should pay for cross domain message.
function calculateIntrinsicGasFee(bytes memory /* _calldata */) external pure returns (uint256) {
return 0;
}

/// @notice Return the hash of a L1 message.
function computeTransactionHash(
address /* sender */,
uint256 /* queueIndex */,
uint256 /* value */,
address /* target */,
uint256 /* gasLimit */,
bytes calldata /* data */
) external pure returns (bytes32) {
return 0;
}

/// @notice Append a L1 to L2 message into this contract.
/// @param target The address of target contract to call in L2.
/// @param gasLimit The maximum gas should be used for relay this message in L2.
/// @param data The calldata passed to target contract.
function appendCrossDomainMessage(address target, uint256 gasLimit, bytes calldata data) external {}

/// @notice Append an enforced transaction to this contract.
/// @dev The address of sender should be an EOA.
/// @param sender The address of sender who will initiate this transaction in L2.
/// @param target The address of target contract to call in L2.
/// @param value The value passed
/// @param gasLimit The maximum gas should be used for this transaction in L2.
/// @param data The calldata passed to target contract.
function appendEnforcedTransaction(
address sender,
address target,
uint256 value,
uint256 gasLimit,
bytes calldata data
) external {}

/// @notice Pop finalized messages from queue.
///
/// @dev We can pop at most 256 messages each time. And if the message is not skipped,
/// the corresponding entry will be cleared.
///
/// @param startIndex The start index to pop.
/// @param count The number of messages to pop.
/// @param skippedBitmap A bitmap indicates whether a message is skipped.
function popCrossDomainMessage(uint256 startIndex, uint256 count, uint256 skippedBitmap) external {}

/// @notice Drop a skipped message from the queue.
function dropCrossDomainMessage(uint256 index) external {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity 0.8.19;

import {MockScrollL1CrossDomainMessenger} from "../../mocks/scroll/MockScrollL1CrossDomainMessenger.sol";
import {MockScrollL2CrossDomainMessenger} from "../../mocks/scroll/MockScrollL2CrossDomainMessenger.sol";
import {MockScrollL1MessageQueue} from "../../mocks/scroll/MockScrollL1MessageQueue.sol";
import {ScrollSequencerUptimeFeed} from "../../../dev/scroll/ScrollSequencerUptimeFeed.sol";
import {SequencerUptimeFeed} from "../../../dev/SequencerUptimeFeed.sol";
import {ScrollValidator} from "../../../dev/scroll/ScrollValidator.sol";
Expand All @@ -16,6 +17,7 @@ contract ScrollValidatorTest is L2EPTest {
/// L2EP contracts
MockScrollL1CrossDomainMessenger internal s_mockScrollL1CrossDomainMessenger;
MockScrollL2CrossDomainMessenger internal s_mockScrollL2CrossDomainMessenger;
MockScrollL1MessageQueue internal s_mockScrollL1MessageQueue;
ScrollSequencerUptimeFeed internal s_scrollSequencerUptimeFeed;
ScrollValidator internal s_scrollValidator;

Expand All @@ -33,6 +35,7 @@ contract ScrollValidatorTest is L2EPTest {
function setUp() public {
s_mockScrollL1CrossDomainMessenger = new MockScrollL1CrossDomainMessenger();
s_mockScrollL2CrossDomainMessenger = new MockScrollL2CrossDomainMessenger();
s_mockScrollL1MessageQueue = new MockScrollL1MessageQueue();

s_scrollSequencerUptimeFeed = new ScrollSequencerUptimeFeed(
address(s_mockScrollL1CrossDomainMessenger),
Expand All @@ -43,6 +46,7 @@ contract ScrollValidatorTest is L2EPTest {
s_scrollValidator = new ScrollValidator(
address(s_mockScrollL1CrossDomainMessenger),
address(s_scrollSequencerUptimeFeed),
address(s_mockScrollL1MessageQueue),
INIT_GAS_LIMIT
);
}
Expand Down
9 changes: 9 additions & 0 deletions contracts/test/v0.8/dev/ScrollValidator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe('ScrollValidator', () => {
const L2_SEQ_STATUS_RECORDER_ADDRESS =
'0x491B1dDA0A8fa069bbC1125133A975BF4e85a91b'
let scrollValidator: Contract
let l1MessageQueue: Contract
let scrollUptimeFeedFactory: ContractFactory
let mockScrollL1CrossDomainMessenger: Contract
let deployer: SignerWithAddress
Expand All @@ -35,6 +36,13 @@ describe('ScrollValidator', () => {
mockScrollL1CrossDomainMessenger =
await mockScrollL1CrossDomainMessengerFactory.deploy()

// Scroll Message Queue contract on L1
const l1MessageQueueFactory = await ethers.getContractFactory(
'src/v0.8/l2ep/test/mocks/scroll/MockScrollL1MessageQueue.sol:MockScrollL1MessageQueue',
deployer,
)
l1MessageQueue = await l1MessageQueueFactory.deploy()

// Contract under test
const scrollValidatorFactory = await ethers.getContractFactory(
'src/v0.8/l2ep/dev/scroll/ScrollValidator.sol:ScrollValidator',
Expand All @@ -44,6 +52,7 @@ describe('ScrollValidator', () => {
scrollValidator = await scrollValidatorFactory.deploy(
mockScrollL1CrossDomainMessenger.address,
L2_SEQ_STATUS_RECORDER_ADDRESS,
l1MessageQueue.address,
GAS_LIMIT,
)
})
Expand Down

0 comments on commit 0aa68b2

Please sign in to comment.