This repository has been archived by the owner on Dec 5, 2021. It is now read-only.
forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #25 from omgnetwork/lp-amm-relayer
Add docker file for the alt_messenger and update LP contracts
- Loading branch information
Showing
29 changed files
with
599 additions
and
13,510 deletions.
There are no files selected for viewing
287 changes: 287 additions & 0 deletions
287
...s/contracts/optimistic-ethereum/OVM/bridge/messaging/OVM_L1CustomCrossDomainMessenger.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,287 @@ | ||
// SPDX-License-Identifier: MIT | ||
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_AddressManager } from "../../../libraries/resolver/Lib_AddressManager.sol"; | ||
import { Lib_SecureMerkleTrie } from "../../../libraries/trie/Lib_SecureMerkleTrie.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"; | ||
|
||
/** | ||
* @title OVM_L1CrossDomainMessenger | ||
* @dev The L1 Cross Domain Messenger contract sends messages from L1 to L2, and relays messages from L2 onto L1. | ||
* In the event that a message sent from L1 to L2 is rejected for exceeding the L2 epoch gas limit, it can be resubmitted | ||
* via this contract's replay function. | ||
* | ||
* Compiler used: solc | ||
* Runtime target: EVM | ||
*/ | ||
contract OVM_L1CrossDomainMessenger is iOVM_L1CrossDomainMessenger, Abs_BaseCrossDomainMessenger, Lib_AddressResolver { | ||
|
||
/*************** | ||
* Constructor * | ||
***************/ | ||
|
||
/** | ||
* Pass a default zero address to the address resolver. This will be updated when initialized. | ||
*/ | ||
constructor() | ||
Lib_AddressResolver(address(0)) | ||
{} | ||
|
||
/** | ||
* @param _libAddressManager Address of the Address Manager. | ||
*/ | ||
function initialize( | ||
address _libAddressManager | ||
) | ||
public | ||
{ | ||
require(address(libAddressManager) == address(0), "L1CrossDomainMessenger already intialized."); | ||
libAddressManager = Lib_AddressManager(_libAddressManager); | ||
xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; | ||
} | ||
|
||
|
||
/********************** | ||
* Function Modifiers * | ||
**********************/ | ||
|
||
/** | ||
* Modifier to enforce that, if configured, only the OVM_L2MessageRelayer contract may successfully call a method. | ||
*/ | ||
modifier onlyRelayer() { | ||
address relayer = resolve("OVM_L2MessageRelayer"); | ||
if (relayer != address(0)) { | ||
require( | ||
msg.sender == relayer, | ||
"Only OVM_L2MessageRelayer can relay L2-to-L1 messages." | ||
); | ||
} | ||
_; | ||
} | ||
|
||
|
||
/******************** | ||
* Public Functions * | ||
********************/ | ||
|
||
/** | ||
* Relays a cross domain message to a contract. | ||
* @inheritdoc iOVM_L1CrossDomainMessenger | ||
*/ | ||
function relayMessage( | ||
address _target, | ||
address _sender, | ||
bytes memory _message, | ||
uint256 _messageNonce, | ||
L2MessageInclusionProof memory _proof | ||
) | ||
override | ||
public | ||
onlyRelayer() | ||
{ | ||
bytes memory xDomainCalldata = _getXDomainCalldata( | ||
_target, | ||
_sender, | ||
_message, | ||
_messageNonce | ||
); | ||
|
||
require( | ||
_verifyXDomainMessage( | ||
xDomainCalldata, | ||
_proof | ||
) == true, | ||
"Provided message could not be verified." | ||
); | ||
|
||
bytes32 xDomainCalldataHash = keccak256(xDomainCalldata); | ||
|
||
require( | ||
successfulMessages[xDomainCalldataHash] == false, | ||
"Provided message has already been received." | ||
); | ||
|
||
xDomainMsgSender = _sender; | ||
(bool success, ) = _target.call(_message); | ||
xDomainMsgSender = DEFAULT_XDOMAIN_SENDER; | ||
|
||
// Mark the message as received if the call was successful. Ensures that a message can be | ||
// relayed multiple times in the case that the call reverted. | ||
if (success == true) { | ||
successfulMessages[xDomainCalldataHash] = true; | ||
emit RelayedMessage(xDomainCalldataHash); | ||
} | ||
|
||
// Store an identifier that can be used to prove that the given message was relayed by some | ||
// user. Gives us an easy way to pay relayers for their work. | ||
bytes32 relayId = keccak256( | ||
abi.encodePacked( | ||
xDomainCalldata, | ||
msg.sender, | ||
block.number | ||
) | ||
); | ||
relayedMessages[relayId] = true; | ||
} | ||
|
||
/** | ||
* Replays a cross domain message to the target messenger. | ||
* @inheritdoc iOVM_L1CrossDomainMessenger | ||
*/ | ||
function replayMessage( | ||
address _target, | ||
address _sender, | ||
bytes memory _message, | ||
uint256 _messageNonce, | ||
uint32 _gasLimit | ||
) | ||
override | ||
public | ||
{ | ||
bytes memory xDomainCalldata = _getXDomainCalldata( | ||
_target, | ||
_sender, | ||
_message, | ||
_messageNonce | ||
); | ||
|
||
require( | ||
sentMessages[keccak256(xDomainCalldata)] == true, | ||
"Provided message has not already been sent." | ||
); | ||
|
||
_sendXDomainMessage(xDomainCalldata, _gasLimit); | ||
} | ||
|
||
|
||
/********************** | ||
* Internal Functions * | ||
**********************/ | ||
|
||
/** | ||
* Verifies that the given message is valid. | ||
* @param _xDomainCalldata Calldata to verify. | ||
* @param _proof Inclusion proof for the message. | ||
* @return Whether or not the provided message is valid. | ||
*/ | ||
function _verifyXDomainMessage( | ||
bytes memory _xDomainCalldata, | ||
L2MessageInclusionProof memory _proof | ||
) | ||
internal | ||
view | ||
returns ( | ||
bool | ||
) | ||
{ | ||
return ( | ||
_verifyStateRootProof(_proof) | ||
&& _verifyStorageProof(_xDomainCalldata, _proof) | ||
); | ||
} | ||
|
||
/** | ||
* Verifies that the state root within an inclusion proof is valid. | ||
* @param _proof Message inclusion proof. | ||
* @return Whether or not the provided proof is valid. | ||
*/ | ||
function _verifyStateRootProof( | ||
L2MessageInclusionProof memory _proof | ||
) | ||
internal | ||
view | ||
returns ( | ||
bool | ||
) | ||
{ | ||
iOVM_StateCommitmentChain ovmStateCommitmentChain = iOVM_StateCommitmentChain(resolve("OVM_StateCommitmentChain")); | ||
|
||
return ( | ||
ovmStateCommitmentChain.verifyStateCommitment( | ||
_proof.stateRoot, | ||
_proof.stateRootBatchHeader, | ||
_proof.stateRootProof | ||
) | ||
); | ||
} | ||
|
||
/** | ||
* Verifies that the storage proof within an inclusion proof is valid. | ||
* @param _xDomainCalldata Encoded message calldata. | ||
* @param _proof Message inclusion proof. | ||
* @return Whether or not the provided proof is valid. | ||
*/ | ||
function _verifyStorageProof( | ||
bytes memory _xDomainCalldata, | ||
L2MessageInclusionProof memory _proof | ||
) | ||
internal | ||
view | ||
returns ( | ||
bool | ||
) | ||
{ | ||
bytes32 storageKey = keccak256( | ||
abi.encodePacked( | ||
keccak256( | ||
abi.encodePacked( | ||
_xDomainCalldata, | ||
resolve("OVM_L2CrossDomainMessenger") | ||
) | ||
), | ||
uint256(0) | ||
) | ||
); | ||
|
||
( | ||
bool exists, | ||
bytes memory encodedMessagePassingAccount | ||
) = Lib_SecureMerkleTrie.get( | ||
abi.encodePacked(0x4200000000000000000000000000000000000000), | ||
_proof.stateTrieWitness, | ||
_proof.stateRoot | ||
); | ||
|
||
require( | ||
exists == true, | ||
"Message passing predeploy has not been initialized or invalid proof provided." | ||
); | ||
|
||
Lib_OVMCodec.EVMAccount memory account = Lib_OVMCodec.decodeEVMAccount( | ||
encodedMessagePassingAccount | ||
); | ||
|
||
return Lib_SecureMerkleTrie.verifyInclusionProof( | ||
abi.encodePacked(storageKey), | ||
abi.encodePacked(uint8(1)), | ||
_proof.storageTrieWitness, | ||
account.storageRoot | ||
); | ||
} | ||
|
||
/** | ||
* Sends a cross domain message. | ||
* @param _message Message to send. | ||
* @param _gasLimit OVM gas limit for the message. | ||
*/ | ||
function _sendXDomainMessage( | ||
bytes memory _message, | ||
uint256 _gasLimit | ||
) | ||
override | ||
internal | ||
{ | ||
revert("Sending via this messenger is disabled"); | ||
} | ||
} |
62 changes: 62 additions & 0 deletions
62
packages/contracts/deploy/017-OVM_L1CustomCrossDomainMessenger.deploy.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
/* Imports: External */ | ||
import { DeployFunction } from 'hardhat-deploy/dist/types' | ||
|
||
/* Imports: Internal */ | ||
import { getDeployedContract } from '../src/hardhat-deploy-ethers' | ||
|
||
const deployFn: DeployFunction = async (hre) => { | ||
const { deploy } = hre.deployments | ||
const { deployer } = await hre.getNamedAccounts() | ||
|
||
const Lib_AddressManager = await getDeployedContract( | ||
hre, | ||
'Lib_AddressManager', | ||
{ | ||
signerOrProvider: deployer, | ||
} | ||
) | ||
|
||
const result = await deploy('OVM_L1CustomCrossDomainMessenger', { | ||
from: deployer, | ||
args: [], | ||
log: true, | ||
}) | ||
|
||
if (!result.newlyDeployed) { | ||
return | ||
} | ||
|
||
const OVM_L1CustomCrossDomainMessenger = await getDeployedContract( | ||
hre, | ||
'OVM_L1CustomCrossDomainMessenger', | ||
{ | ||
signerOrProvider: deployer, | ||
} | ||
) | ||
|
||
// NOTE: this initialization is *not* technically required (we only need to initialize the proxy) | ||
// but it feels safer to initialize this anyway. Otherwise someone else could come along and | ||
// initialize this. | ||
await OVM_L1CustomCrossDomainMessenger.initialize(Lib_AddressManager.address) | ||
|
||
const libAddressManager = await OVM_L1CustomCrossDomainMessenger.libAddressManager() | ||
if (libAddressManager !== Lib_AddressManager.address) { | ||
throw new Error( | ||
`\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + | ||
`OVM_L1CustomCrossDomainMessenger could not be succesfully initialized.\n` + | ||
`Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + | ||
`Actual address after initialization: ${libAddressManager}\n` + | ||
`This could indicate a compromised deployment.` | ||
) | ||
} | ||
|
||
await Lib_AddressManager.setAddress( | ||
'OVM_L1CustomCrossDomainMessenger', | ||
result.address | ||
) | ||
} | ||
|
||
deployFn.dependencies = ['Lib_AddressManager'] | ||
deployFn.tags = ['OVM_L1CustomCrossDomainMessenger'] | ||
|
||
export default deployFn |
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.