Commit 200a083e authored by Elena Gesheva's avatar Elena Gesheva Committed by Kelvin Fichter

Reduce gas costs of deposits (#667)

* Remove messageNonce from BaseCrossDomainMessenger and use CTC queue lenght instead

Remove Abs_BaseCrossDomainMessenger and restore dedicated nonce generation in OVM_L2CrossDomainMessenger

Fix typo

* Remove sentMessages mapping from L1CrossDomainMessenger storage
and use the nonce to check for existence of replayed transaction

* Refactor out common library function for getting cross domain calldata

* Post rebase fixes

* Use the queueIndex to check the transaction was enqueued

* Fix tests for L1CrossDomainMessenger.replayMessage
Also make that test work with an actual CanonicalTransactionChain implementation rather than a smock

* Lint fixes

* Optimise the resolve calls into the AddressManager lib

* Rename the nonce parameter to be clear

* Update test name
Co-authored-by: default avatarben-chain <ben@pseudonym.party>

* Rename getXDomainCalldata to encodeXDomainCalldata to match the new Lib_CrossDomainUtils
Co-authored-by: default avatarben-chain <ben@pseudonym.party>
parent 2e72fd90
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Interface Imports */
import { iAbs_BaseCrossDomainMessenger } from "../../../iOVM/bridge/messaging/iAbs_BaseCrossDomainMessenger.sol";
/**
* @title Abs_BaseCrossDomainMessenger
* @dev The Base Cross Domain Messenger is an abstract contract providing the interface and common
* functionality used in the L1 and L2 Cross Domain Messengers. It can also serve as a template for
* developers wishing to implement a custom bridge contract to suit their needs.
*
* Compiler used: defined by child contract
* Runtime target: defined by child contract
*/
abstract contract Abs_BaseCrossDomainMessenger is iAbs_BaseCrossDomainMessenger {
/*************
* Constants *
*************/
// The default x-domain message sender being set to a non-zero value makes
// deployment a bit more expensive, but in exchange the refund on every call to
// `relayMessage` by the L1 and L2 messengers will be higher.
address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;
/*************
* Variables *
*************/
mapping (bytes32 => bool) public relayedMessages;
mapping (bytes32 => bool) public successfulMessages;
mapping (bytes32 => bool) public sentMessages;
uint256 public messageNonce;
address internal xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;
/***************
* Constructor *
***************/
constructor() {}
/********************
* Public Functions *
********************/
function xDomainMessageSender()
public
override
view
returns (
address
)
{
require(xDomainMsgSender != DEFAULT_XDOMAIN_SENDER, "xDomainMessageSender is not set");
return xDomainMsgSender;
}
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
)
override
public
{
bytes memory xDomainCalldata = _getXDomainCalldata(
_target,
msg.sender,
_message,
messageNonce
);
messageNonce += 1;
sentMessages[keccak256(xDomainCalldata)] = true;
_sendXDomainMessage(xDomainCalldata, _gasLimit);
emit SentMessage(xDomainCalldata);
}
/**********************
* Internal Functions *
**********************/
/**
* Generates the correct cross domain calldata for a message.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @return ABI encoded cross domain calldata.
*/
function _getXDomainCalldata(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
)
internal
pure
returns (
bytes memory
)
{
return abi.encodeWithSignature(
"relayMessage(address,address,bytes,uint256)",
_target,
_sender,
_message,
_messageNonce
);
}
/**
* Sends a cross domain message.
* param // Message to send.
* param // Gas limit for the provided message.
*/
function _sendXDomainMessage(
bytes memory, // _message,
uint256 // _gasLimit
)
virtual
internal
{
revert("Implement me in child contracts!");
}
}
......@@ -3,19 +3,17 @@ pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_OVMCodec } from "../../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_OVMCodec } from "../../../libraries/codec/Lib_OVMCodec.sol";
import { Lib_AddressManager } from "../../../libraries/resolver/Lib_AddressManager.sol";
import { Lib_SecureMerkleTrie } from "../../../libraries/trie/Lib_SecureMerkleTrie.sol";
import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol";
/* Interface Imports */
import { iOVM_L1CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L1CrossDomainMessenger.sol";
import { iOVM_CanonicalTransactionChain } from "../../../iOVM/chain/iOVM_CanonicalTransactionChain.sol";
import { iOVM_StateCommitmentChain } from "../../../iOVM/chain/iOVM_StateCommitmentChain.sol";
/* Contract Imports */
import { Abs_BaseCrossDomainMessenger } from "./Abs_BaseCrossDomainMessenger.sol";
/* External Imports */
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { PausableUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
......@@ -32,7 +30,6 @@ import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/
*/
contract OVM_L1CrossDomainMessenger is
iOVM_L1CrossDomainMessenger,
Abs_BaseCrossDomainMessenger,
Lib_AddressResolver,
OwnableUpgradeable,
PausableUpgradeable,
......@@ -51,11 +48,24 @@ contract OVM_L1CrossDomainMessenger is
bytes32 indexed _xDomainCalldataHash
);
/*************
* Constants *
*************/
// The default x-domain message sender being set to a non-zero value makes
// deployment a bit more expensive, but in exchange the refund on every call to
// `relayMessage` by the L1 and L2 messengers will be higher.
address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;
/**********************
* Contract Variables *
**********************/
mapping (bytes32 => bool) public blockedMessages;
mapping (bytes32 => bool) public relayedMessages;
mapping (bytes32 => bool) public successfulMessages;
address internal xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;
/***************
* Constructor *
......@@ -155,6 +165,48 @@ contract OVM_L1CrossDomainMessenger is
emit MessageAllowed(_xDomainCalldataHash);
}
function xDomainMessageSender()
public
override
view
returns (
address
)
{
require(xDomainMsgSender != DEFAULT_XDOMAIN_SENDER, "xDomainMessageSender is not set");
return xDomainMsgSender;
}
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
)
override
public
{
address ovmCanonicalTransactionChain = resolve("OVM_CanonicalTransactionChain");
// Use the CTC queue length as nonce
uint40 nonce = iOVM_CanonicalTransactionChain(ovmCanonicalTransactionChain).getQueueLength();
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
msg.sender,
_message,
nonce
);
address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
_sendXDomainMessage(ovmCanonicalTransactionChain, l2CrossDomainMessenger, xDomainCalldata, _gasLimit);
emit SentMessage(xDomainCalldata);
}
/**
* Relays a cross domain message to a contract.
* @inheritdoc iOVM_L1CrossDomainMessenger
......@@ -172,7 +224,7 @@ contract OVM_L1CrossDomainMessenger is
onlyRelayer
whenNotPaused
{
bytes memory xDomainCalldata = _getXDomainCalldata(
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
_sender,
_message,
......@@ -232,25 +284,40 @@ contract OVM_L1CrossDomainMessenger is
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
uint256 _queueIndex,
uint32 _gasLimit
)
override
public
{
bytes memory xDomainCalldata = _getXDomainCalldata(
_target,
_sender,
_message,
_messageNonce
// Verify that the message is in the queue:
address canonicalTransactionChain = resolve("OVM_CanonicalTransactionChain");
Lib_OVMCodec.QueueElement memory element = iOVM_CanonicalTransactionChain(canonicalTransactionChain).getQueueElement(_queueIndex);
address l2CrossDomainMessenger = resolve("OVM_L2CrossDomainMessenger");
// Compute the transactionHash
bytes32 transactionHash = keccak256(
abi.encode(
address(this),
l2CrossDomainMessenger,
_gasLimit,
_message
)
);
require(
sentMessages[keccak256(xDomainCalldata)] == true,
"Provided message has not already been sent."
transactionHash == element.transactionHash,
"Provided message has not been enqueued."
);
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
_sender,
_message,
_queueIndex
);
_sendXDomainMessage(xDomainCalldata, _gasLimit);
_sendXDomainMessage(canonicalTransactionChain, l2CrossDomainMessenger, xDomainCalldata, _gasLimit);
}
......@@ -364,18 +431,21 @@ contract OVM_L1CrossDomainMessenger is
/**
* Sends a cross domain message.
* @param _canonicalTransactionChain Address of the OVM_CanonicalTransactionChain instance.
* @param _l2CrossDomainMessenger Address of the OVM_L2CrossDomainMessenger instance.
* @param _message Message to send.
* @param _gasLimit OVM gas limit for the message.
*/
function _sendXDomainMessage(
address _canonicalTransactionChain,
address _l2CrossDomainMessenger,
bytes memory _message,
uint256 _gasLimit
)
override
internal
{
iOVM_CanonicalTransactionChain(resolve("OVM_CanonicalTransactionChain")).enqueue(
resolve("OVM_L2CrossDomainMessenger"),
iOVM_CanonicalTransactionChain(_canonicalTransactionChain).enqueue(
_l2CrossDomainMessenger,
_gasLimit,
_message
);
......
......@@ -4,14 +4,15 @@ pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_AddressResolver } from "../../../libraries/resolver/Lib_AddressResolver.sol";
import { Lib_CrossDomainUtils } from "../../../libraries/bridge/Lib_CrossDomainUtils.sol";
/* Interface Imports */
import { iOVM_L2CrossDomainMessenger } from "../../../iOVM/bridge/messaging/iOVM_L2CrossDomainMessenger.sol";
import { iOVM_L1MessageSender } from "../../../iOVM/predeploys/iOVM_L1MessageSender.sol";
import { iOVM_L2ToL1MessagePasser } from "../../../iOVM/predeploys/iOVM_L2ToL1MessagePasser.sol";
/* Contract Imports */
import { Abs_BaseCrossDomainMessenger } from "./Abs_BaseCrossDomainMessenger.sol";
/* External Imports */
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/* External Imports */
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
......@@ -26,11 +27,29 @@ import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.s
*/
contract OVM_L2CrossDomainMessenger is
iOVM_L2CrossDomainMessenger,
Abs_BaseCrossDomainMessenger,
Lib_AddressResolver,
ReentrancyGuard
{
/*************
* Constants *
*************/
// The default x-domain message sender being set to a non-zero value makes
// deployment a bit more expensive, but in exchange the refund on every call to
// `relayMessage` by the L1 and L2 messengers will be higher.
address internal constant DEFAULT_XDOMAIN_SENDER = 0x000000000000000000000000000000000000dEaD;
/*************
* Variables *
*************/
mapping (bytes32 => bool) public relayedMessages;
mapping (bytes32 => bool) public successfulMessages;
mapping (bytes32 => bool) public sentMessages;
uint256 public messageNonce;
address internal xDomainMsgSender = DEFAULT_XDOMAIN_SENDER;
/***************
* Constructor *
***************/
......@@ -38,18 +57,53 @@ contract OVM_L2CrossDomainMessenger is
/**
* @param _libAddressManager Address of the Address Manager.
*/
constructor(
address _libAddressManager
)
Lib_AddressResolver(_libAddressManager)
ReentrancyGuard()
{}
constructor(address _libAddressManager) Lib_AddressResolver(_libAddressManager) ReentrancyGuard() {}
/********************
* Public Functions *
********************/
function xDomainMessageSender()
public
override
view
returns (
address
)
{
require(xDomainMsgSender != DEFAULT_XDOMAIN_SENDER, "xDomainMessageSender is not set");
return xDomainMsgSender;
}
/**
* Sends a cross domain message to the target messenger.
* @param _target Target contract address.
* @param _message Message to send to the target.
* @param _gasLimit Gas limit for the provided message.
*/
function sendMessage(
address _target,
bytes memory _message,
uint32 _gasLimit
)
override
public
{
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
msg.sender,
_message,
messageNonce
);
messageNonce += 1;
sentMessages[keccak256(xDomainCalldata)] = true;
_sendXDomainMessage(xDomainCalldata, _gasLimit);
emit SentMessage(xDomainCalldata);
}
/**
* Relays a cross domain message to a contract.
* @inheritdoc iOVM_L2CrossDomainMessenger
......@@ -69,7 +123,7 @@ contract OVM_L2CrossDomainMessenger is
"Provided message could not be verified."
);
bytes memory xDomainCalldata = _getXDomainCalldata(
bytes memory xDomainCalldata = Lib_CrossDomainUtils.encodeXDomainCalldata(
_target,
_sender,
_message,
......@@ -150,7 +204,6 @@ contract OVM_L2CrossDomainMessenger is
bytes memory _message,
uint256 // _gasLimit
)
override
internal
{
iOVM_L2ToL1MessagePasser(resolve("OVM_L2ToL1MessagePasser")).passMessageToL1(_message);
......
......@@ -22,7 +22,6 @@ contract OVM_L2ToL1MessagePasser is iOVM_L2ToL1MessagePasser {
mapping (bytes32 => bool) public sentMessages;
/********************
* Public Functions *
********************/
......
......@@ -51,14 +51,14 @@ interface iOVM_L1CrossDomainMessenger is iAbs_BaseCrossDomainMessenger {
* @param _target Target contract address.
* @param _sender Original sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @param _queueIndex CTC Queue index for the message to replay.
* @param _gasLimit Gas limit for the provided message.
*/
function replayMessage(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce,
uint256 _queueIndex,
uint32 _gasLimit
) external;
}
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;
pragma experimental ABIEncoderV2;
/* Library Imports */
import { Lib_RLPReader } from "../rlp/Lib_RLPReader.sol";
/**
* @title Lib_CrossDomainUtils
*/
library Lib_CrossDomainUtils {
/**
* Generates the correct cross domain calldata for a message.
* @param _target Target contract address.
* @param _sender Message sender address.
* @param _message Message to send to the target.
* @param _messageNonce Nonce for the provided message.
* @return ABI encoded cross domain calldata.
*/
function encodeXDomainCalldata(
address _target,
address _sender,
bytes memory _message,
uint256 _messageNonce
)
internal
pure
returns (
bytes memory
)
{
return abi.encodeWithSignature(
"relayMessage(address,address,bytes,uint256)",
_target,
_sender,
_message,
_messageNonce
);
}
}
......@@ -14,12 +14,16 @@ import {
NON_ZERO_ADDRESS,
DUMMY_BATCH_HEADERS,
DUMMY_BATCH_PROOFS,
FORCE_INCLUSION_PERIOD_SECONDS,
FORCE_INCLUSION_PERIOD_BLOCKS,
TrieTestGenerator,
getNextBlockNumber,
getXDomainCalldata,
encodeXDomainCalldata,
} from '../../../../helpers'
import { keccak256 } from 'ethers/lib/utils'
const MAX_GAS_LIMIT = 8_000_000
const deployProxyXDomainMessenger = async (
addressManager: Contract,
l1XDomainMessenger: Contract
......@@ -48,8 +52,13 @@ describe('OVM_L1CrossDomainMessenger', () => {
let Mock__TargetContract: MockContract
let Mock__OVM_L2CrossDomainMessenger: MockContract
let Mock__OVM_CanonicalTransactionChain: MockContract
let Mock__OVM_StateCommitmentChain: MockContract
let Factory__OVM_CanonicalTransactionChain: ContractFactory
let Factory__OVM_ChainStorageContainer: ContractFactory
let Factory__OVM_L1CrossDomainMessenger: ContractFactory
let OVM_CanonicalTransactionChain: Contract
before(async () => {
Mock__TargetContract = await smockit(
await ethers.getContractFactory('Helper_SimpleProxy')
......@@ -57,9 +66,6 @@ describe('OVM_L1CrossDomainMessenger', () => {
Mock__OVM_L2CrossDomainMessenger = await smockit(
await ethers.getContractFactory('OVM_L2CrossDomainMessenger')
)
Mock__OVM_CanonicalTransactionChain = await smockit(
await ethers.getContractFactory('OVM_CanonicalTransactionChain')
)
Mock__OVM_StateCommitmentChain = await smockit(
await ethers.getContractFactory('OVM_StateCommitmentChain')
)
......@@ -69,23 +75,53 @@ describe('OVM_L1CrossDomainMessenger', () => {
Mock__OVM_L2CrossDomainMessenger.address
)
await setProxyTarget(
AddressManager,
'OVM_CanonicalTransactionChain',
Mock__OVM_CanonicalTransactionChain
)
await setProxyTarget(
AddressManager,
'OVM_StateCommitmentChain',
Mock__OVM_StateCommitmentChain
)
})
let Factory__OVM_L1CrossDomainMessenger: ContractFactory
before(async () => {
Factory__OVM_CanonicalTransactionChain = await ethers.getContractFactory(
'OVM_CanonicalTransactionChain'
)
Factory__OVM_ChainStorageContainer = await ethers.getContractFactory(
'OVM_ChainStorageContainer'
)
Factory__OVM_L1CrossDomainMessenger = await ethers.getContractFactory(
'OVM_L1CrossDomainMessenger'
)
OVM_CanonicalTransactionChain = await Factory__OVM_CanonicalTransactionChain.deploy(
AddressManager.address,
FORCE_INCLUSION_PERIOD_SECONDS,
FORCE_INCLUSION_PERIOD_BLOCKS,
MAX_GAS_LIMIT
)
const batches = await Factory__OVM_ChainStorageContainer.deploy(
AddressManager.address,
'OVM_CanonicalTransactionChain'
)
const queue = await Factory__OVM_ChainStorageContainer.deploy(
AddressManager.address,
'OVM_CanonicalTransactionChain'
)
await AddressManager.setAddress(
'OVM_ChainStorageContainer:CTC:batches',
batches.address
)
await AddressManager.setAddress(
'OVM_ChainStorageContainer:CTC:queue',
queue.address
)
await AddressManager.setAddress(
'OVM_CanonicalTransactionChain',
OVM_CanonicalTransactionChain.address
)
})
let OVM_L1CrossDomainMessenger: Contract
......@@ -117,6 +153,26 @@ describe('OVM_L1CrossDomainMessenger', () => {
})
})
const getTransactionHash = (
sender: string,
target: string,
gasLimit: number,
data: string
): string => {
return keccak256(encodeQueueTransaction(sender, target, gasLimit, data))
}
const encodeQueueTransaction = (
sender: string,
target: string,
gasLimit: number,
data: string
): string => {
return ethers.utils.defaultAbiCoder.encode(
['address', 'address', 'uint256', 'bytes'],
[sender, target, gasLimit, data]
)
}
describe('sendMessage', () => {
const target = NON_ZERO_ADDRESS
const message = NON_NULL_BYTES32
......@@ -127,13 +183,24 @@ describe('OVM_L1CrossDomainMessenger', () => {
OVM_L1CrossDomainMessenger.sendMessage(target, message, gasLimit)
).to.not.be.reverted
expect(
Mock__OVM_CanonicalTransactionChain.smocked.enqueue.calls[0]
).to.deep.equal([
const calldata = encodeXDomainCalldata(
target,
await signer.getAddress(),
message,
0
)
const transactionHash = getTransactionHash(
OVM_L1CrossDomainMessenger.address,
Mock__OVM_L2CrossDomainMessenger.address,
BigNumber.from(gasLimit),
getXDomainCalldata(target, await signer.getAddress(), message, 0),
])
gasLimit,
calldata
)
const queueLength = await OVM_CanonicalTransactionChain.getQueueLength()
const queueElement = await OVM_CanonicalTransactionChain.getQueueElement(
queueLength - 1
)
expect(queueElement[0]).to.equal(transactionHash)
})
it('should be able to send the same message twice', async () => {
......@@ -150,27 +217,37 @@ describe('OVM_L1CrossDomainMessenger', () => {
const message = NON_NULL_BYTES32
const gasLimit = 100_000
it('should revert if the message does not exist', async () => {
it('should revert if given the wrong queue index', async () => {
await OVM_L1CrossDomainMessenger.sendMessage(target, message, 100_001)
const queueLength = await OVM_CanonicalTransactionChain.getQueueLength()
await expect(
OVM_L1CrossDomainMessenger.replayMessage(
target,
await signer.getAddress(),
message,
0,
queueLength - 1,
gasLimit
)
).to.be.revertedWith('Provided message has not already been sent.')
).to.be.revertedWith('Provided message has not been enqueued.')
})
it('should succeed if the message exists', async () => {
await OVM_L1CrossDomainMessenger.sendMessage(target, message, gasLimit)
const queueLength = await OVM_CanonicalTransactionChain.getQueueLength()
const calldata = encodeXDomainCalldata(
target,
await signer.getAddress(),
message,
queueLength - 1
)
await expect(
OVM_L1CrossDomainMessenger.replayMessage(
target,
Mock__OVM_L2CrossDomainMessenger.address,
await signer.getAddress(),
message,
0,
calldata,
queueLength - 1,
gasLimit
)
).to.not.be.reverted
......@@ -190,7 +267,7 @@ describe('OVM_L1CrossDomainMessenger', () => {
])
sender = await signer.getAddress()
calldata = getXDomainCalldata(target, sender, message, 0)
calldata = encodeXDomainCalldata(target, sender, message, 0)
const precompile = '0x4200000000000000000000000000000000000000'
......
......@@ -11,7 +11,7 @@ import {
setProxyTarget,
NON_NULL_BYTES32,
NON_ZERO_ADDRESS,
getXDomainCalldata,
encodeXDomainCalldata,
getNextBlockNumber,
} from '../../../../helpers'
import { solidityKeccak256 } from 'ethers/lib/utils'
......@@ -89,7 +89,7 @@ describe('OVM_L2CrossDomainMessenger', () => {
expect(
Mock__OVM_L2ToL1MessagePasser.smocked.passMessageToL1.calls[0]
).to.deep.equal([
getXDomainCalldata(target, await signer.getAddress(), message, 0),
encodeXDomainCalldata(target, await signer.getAddress(), message, 0),
])
})
......@@ -193,7 +193,7 @@ describe('OVM_L2CrossDomainMessenger', () => {
await OVM_L2CrossDomainMessenger.successfulMessages(
solidityKeccak256(
['bytes'],
[getXDomainCalldata(target, sender, message, 0)]
[encodeXDomainCalldata(target, sender, message, 0)]
)
)
).to.be.true
......@@ -211,7 +211,7 @@ describe('OVM_L2CrossDomainMessenger', () => {
// Calculate xDomainCallData used for indexing
// (within the first call to the L2 Messenger).
const xDomainCallData = getXDomainCalldata(
const xDomainCallData = encodeXDomainCalldata(
OVM_L2CrossDomainMessenger.address,
sender,
reentrantMessage,
......
import { getContractInterface } from '../../../src/contract-defs'
export const getXDomainCalldata = (
export const encodeXDomainCalldata = (
target: string,
sender: string,
message: string,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment