generated from pooltogether/pooltogether-contracts-template
-
Notifications
You must be signed in to change notification settings - Fork 7
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 #61 from pooltogether/pool-2496-optimism-add-contr…
…act-to-bridge-draw Add contracts to bridge draw
- Loading branch information
Showing
9 changed files
with
1,187 additions
and
2 deletions.
There are no files selected for viewing
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,161 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity 0.8.6; | ||
|
||
import { IDrawBeacon } from "@pooltogether/v4-core/contracts/interfaces/IDrawBeacon.sol"; | ||
import { IDrawBuffer } from "@pooltogether/v4-core/contracts/interfaces/IDrawBuffer.sol"; | ||
|
||
import { ISingleMessageDispatcher } from "./interfaces/ISingleMessageDispatcher.sol"; | ||
|
||
/** | ||
* @title PoolTogether V4 DrawDispatcher | ||
* @author PoolTogether Inc Team | ||
* @notice The DrawDispatcher smart contract relies on ERC-5164 to dispatch draws from Ethereum to another L1 or L2 | ||
* where Chainlink VRF 2.0 may not be available to compute draws. | ||
*/ | ||
contract DrawDispatcher { | ||
/** | ||
* @notice Emitted when the `draw` has been dispatched. | ||
* @param dispatcher Address of the dispatcher on Ethereum that dispatched the draw | ||
* @param toChainId ID of the receiving chain | ||
* @param drawExecutor Address of the DrawExecutor on the receiving chain that will push the draw onto the DrawBuffer | ||
* @param draw Draw that was dispatched | ||
*/ | ||
event DrawDispatched( | ||
ISingleMessageDispatcher indexed dispatcher, | ||
uint256 indexed toChainId, | ||
address indexed drawExecutor, | ||
IDrawBeacon.Draw draw | ||
); | ||
|
||
/** | ||
* @notice Emitted when the `draws` have been dispatched. | ||
* @param dispatcher Address of the dispatcher on Ethereum that dispatched the draws | ||
* @param toChainId ID of the receiving chain | ||
* @param drawExecutor Address of the DrawExecutor on the receiving chain that will push the draws onto the DrawBuffer | ||
* @param draws Draws that were dispatched | ||
*/ | ||
event DrawsDispatched( | ||
ISingleMessageDispatcher indexed dispatcher, | ||
uint256 indexed toChainId, | ||
address indexed drawExecutor, | ||
IDrawBeacon.Draw[] draws | ||
); | ||
|
||
/// @notice DrawBuffer from which draws are retrieved. | ||
IDrawBuffer public immutable drawBuffer; | ||
|
||
/** | ||
* @notice DrawDispatcher constructor. | ||
* @param _drawBuffer Address of the DrawBuffer from which draws are retrieved | ||
*/ | ||
constructor(IDrawBuffer _drawBuffer) { | ||
require(address(_drawBuffer) != address(0), "DD/drawBuffer-not-zero-address"); | ||
|
||
drawBuffer = _drawBuffer; | ||
} | ||
|
||
/** | ||
* @notice Retrieves and dispatch the newest recorded draw. | ||
* @param _dispatcher Address of the dispatcher on Ethereum that will be used to dispatch the draw | ||
* @param _toChainId ID of the receiving chain | ||
* @param _drawExecutor Address of the DrawExecutor on the receiving chain that will push the draw onto the DrawBuffer | ||
*/ | ||
function dispatchNewestDraw( | ||
ISingleMessageDispatcher _dispatcher, | ||
uint256 _toChainId, | ||
address _drawExecutor | ||
) external { | ||
IDrawBeacon.Draw memory _newestDraw = drawBuffer.getNewestDraw(); | ||
_dispatchDraw(_dispatcher, _toChainId, _drawExecutor, _newestDraw); | ||
} | ||
|
||
/** | ||
* @notice Retrieves and dispatch draw. | ||
* @dev Will revert if the draw does not exist. | ||
* @param _dispatcher Address of the dispatcher on Ethereum that will be used to dispatch the draw | ||
* @param _toChainId ID of the receiving chain | ||
* @param _drawExecutor Address of the DrawExecutor on the receiving chain that will push the draw onto the DrawBuffer | ||
* @param _drawId Id of the draw to dispatch | ||
*/ | ||
function dispatchDraw( | ||
ISingleMessageDispatcher _dispatcher, | ||
uint256 _toChainId, | ||
address _drawExecutor, | ||
uint32 _drawId | ||
) external { | ||
require(_drawId > 0, "DD/drawId-gt-zero"); | ||
|
||
IDrawBeacon.Draw memory _draw = drawBuffer.getDraw(_drawId); | ||
_dispatchDraw(_dispatcher, _toChainId, _drawExecutor, _draw); | ||
} | ||
|
||
/** | ||
* @notice Retrieves and dispatch draws. | ||
* @dev `_drawIds` must be ordered in ascending and contiguous order. | ||
* @dev Will revert if one of the draw does not exist. | ||
* @param _dispatcher Address of the dispatcher on Ethereum that will be used to dispatch the draw | ||
* @param _toChainId ID of the receiving chain | ||
* @param _drawExecutor Address of the DrawExecutor on the receiving chain that will push the draw onto the DrawBuffer | ||
* @param _drawIds Array of draw ids to dispatch | ||
*/ | ||
function dispatchDraws( | ||
ISingleMessageDispatcher _dispatcher, | ||
uint256 _toChainId, | ||
address _drawExecutor, | ||
uint32[] calldata _drawIds | ||
) external { | ||
IDrawBeacon.Draw[] memory _draws = drawBuffer.getDraws(_drawIds); | ||
|
||
_dispatchMessage( | ||
_dispatcher, | ||
_toChainId, | ||
_drawExecutor, | ||
abi.encodeWithSignature("pushDraws((uint256,uint32,uint64,uint64,uint32)[])", _draws) | ||
); | ||
|
||
emit DrawsDispatched(_dispatcher, _toChainId, _drawExecutor, _draws); | ||
} | ||
|
||
/** | ||
* @notice Dispatch the passed `draw`. | ||
* @param _dispatcher Address of the dispatcher on Ethereum that will be used to dispatch the draw | ||
* @param _toChainId ID of the receiving chain | ||
* @param _drawExecutor Address of the DrawExecutor on the receiving chain that will push the draw onto the DrawBuffer | ||
* @param _draw Draw to dispatch | ||
*/ | ||
function _dispatchDraw( | ||
ISingleMessageDispatcher _dispatcher, | ||
uint256 _toChainId, | ||
address _drawExecutor, | ||
IDrawBeacon.Draw memory _draw | ||
) internal { | ||
_dispatchMessage( | ||
_dispatcher, | ||
_toChainId, | ||
_drawExecutor, | ||
abi.encodeWithSignature("pushDraw((uint256,uint32,uint64,uint64,uint32))", _draw) | ||
); | ||
|
||
emit DrawDispatched(_dispatcher, _toChainId, _drawExecutor, _draw); | ||
} | ||
|
||
/** | ||
* @notice Dispatch encoded call. | ||
* @param _dispatcher Address of the dispatcher on Ethereum that will dispatch the call | ||
* @param _toChainId ID of the receiving chain | ||
* @param _drawExecutor Address of the DrawExecutor on the receiving chain that will receive the call | ||
* @param _data Calldata to dispatch | ||
*/ | ||
function _dispatchMessage( | ||
ISingleMessageDispatcher _dispatcher, | ||
uint256 _toChainId, | ||
address _drawExecutor, | ||
bytes memory _data | ||
) internal { | ||
require(address(_dispatcher) != address(0), "DD/dispatcher-not-zero-address"); | ||
require(_drawExecutor != address(0), "DD/drawExecutor-not-zero-address"); | ||
|
||
_dispatcher.dispatchMessage(_toChainId, _drawExecutor, _data); | ||
} | ||
} |
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,102 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity 0.8.6; | ||
|
||
import "@pooltogether/v4-core/contracts/interfaces/IDrawBuffer.sol"; | ||
|
||
import { ExecutorAware } from "./abstract/ExecutorAware.sol"; | ||
|
||
/** | ||
* @title PoolTogether V4 DrawExecutor | ||
* @author PoolTogether Inc Team | ||
* @notice The DrawExecutor smart contract relies on ERC-5164 to receive draws from Ethereum | ||
* and push them onto the DrawBuffer. | ||
* @dev This contract does not ensure draw ordering and draws should always be bridged in ascending and contiguous order. | ||
*/ | ||
contract DrawExecutor is ExecutorAware { | ||
/** | ||
* @notice Emitted when the `draw` has been pushed. | ||
* @param draw Draw that was pushed | ||
*/ | ||
event DrawPushed(IDrawBeacon.Draw draw); | ||
|
||
/** | ||
* @notice Emitted when the `draws` have been pushed. | ||
* @param draws Draws that were pushed | ||
*/ | ||
event DrawsPushed(IDrawBeacon.Draw[] draws); | ||
|
||
/// @notice ID of the origin chain. | ||
uint256 public immutable originChainId; | ||
|
||
/// @notice DrawDispatcher contract on the origin chain that dispatch the draws. | ||
address public immutable drawDispatcher; | ||
|
||
/// @notice DrawBuffer onto which draws are pushed. | ||
IDrawBuffer public immutable drawBuffer; | ||
|
||
/** | ||
* @notice DrawExecutor constructor. | ||
* @param _originChainId ID of the origin chain | ||
* @param _drawDispatcher Address of the DrawDispatcher on the origin chain that dispatch the draws | ||
* @param _executor Address of the ERC-5164 contract that executes the bridged calls | ||
* @param _drawBuffer Address of the DrawBuffer onto which draws are pushed | ||
*/ | ||
constructor( | ||
uint256 _originChainId, | ||
address _drawDispatcher, | ||
address _executor, | ||
IDrawBuffer _drawBuffer | ||
) ExecutorAware(_executor) { | ||
require(_originChainId != 0, "DE/originChainId-not-zero"); | ||
require(address(_drawDispatcher) != address(0), "DE/drawDispatcher-not-zero-adrs"); | ||
require(address(_drawBuffer) != address(0), "DE/drawBuffer-not-zero-address"); | ||
|
||
originChainId = _originChainId; | ||
drawDispatcher = _drawDispatcher; | ||
drawBuffer = _drawBuffer; | ||
} | ||
|
||
/** | ||
* @notice Push `draw` onto the DrawBuffer. | ||
* @dev Only the `executor` is able to call this function. | ||
* @param _draw Draw to push | ||
*/ | ||
function pushDraw(IDrawBeacon.Draw calldata _draw) external { | ||
_checkSender(); | ||
|
||
drawBuffer.pushDraw(_draw); | ||
|
||
emit DrawPushed(_draw); | ||
} | ||
|
||
/** | ||
* @notice Push `draws` onto the DrawBuffer. | ||
* @dev Only the `executor` is able to call this function. | ||
* @dev `draws` must be ordered in ascending and contiguous order. | ||
* @param _draws Draws to push | ||
*/ | ||
function pushDraws(IDrawBeacon.Draw[] calldata _draws) external { | ||
_checkSender(); | ||
|
||
uint256 _drawsLength = _draws.length; | ||
|
||
for (uint256 i; i < _drawsLength; i++) { | ||
drawBuffer.pushDraw(_draws[i]); | ||
} | ||
|
||
emit DrawsPushed(_draws); | ||
} | ||
|
||
/** | ||
* @notice Checks that: | ||
* - the call has been dispatched from the supported chain | ||
* - the sender on the receiving chain is the executor | ||
* - the sender on the origin chain is the DrawDispatcher | ||
*/ | ||
function _checkSender() internal view { | ||
require(_fromChainId() == originChainId, "DE/l1-chainId-not-supported"); | ||
require(isTrustedExecutor(msg.sender), "DE/l2-sender-not-executor"); | ||
require(_msgSender() == address(drawDispatcher), "DE/l1-sender-not-dispatcher"); | ||
} | ||
} |
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,84 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
|
||
pragma solidity 0.8.6; | ||
|
||
/** | ||
* @title ExecutorAware abstract contract | ||
* @notice The ExecutorAware contract allows contracts on a receiving chain to execute messages from an origin chain. | ||
* These messages are sent by the `MessageDispatcher` contract which live on the origin chain. | ||
* The `MessageExecutor` contract on the receiving chain executes these messages | ||
* and then forward them to an ExecutorAware contract on the receiving chain. | ||
* @dev This contract implements EIP-2771 (https://eips.ethereum.org/EIPS/eip-2771) | ||
* to ensure that messages are sent by a trusted `MessageExecutor` contract. | ||
*/ | ||
abstract contract ExecutorAware { | ||
/* ============ Variables ============ */ | ||
|
||
/// @notice Address of the trusted executor contract. | ||
address public immutable trustedExecutor; | ||
|
||
/* ============ Constructor ============ */ | ||
|
||
/** | ||
* @notice ExecutorAware constructor. | ||
* @param _executor Address of the `MessageExecutor` contract | ||
*/ | ||
constructor(address _executor) { | ||
require(_executor != address(0), "executor-not-zero-address"); | ||
trustedExecutor = _executor; | ||
} | ||
|
||
/* ============ External Functions ============ */ | ||
|
||
/** | ||
* @notice Check which executor this contract trust. | ||
* @param _executor Address to check | ||
*/ | ||
function isTrustedExecutor(address _executor) public view returns (bool) { | ||
return _executor == trustedExecutor; | ||
} | ||
|
||
/* ============ Internal Functions ============ */ | ||
|
||
/** | ||
* @notice Retrieve messageId from message data. | ||
* @return _msgDataMessageId ID uniquely identifying the message that was executed | ||
*/ | ||
function _messageId() internal pure returns (bytes32 _msgDataMessageId) { | ||
_msgDataMessageId; | ||
|
||
if (msg.data.length >= 84) { | ||
assembly { | ||
_msgDataMessageId := calldataload(sub(calldatasize(), 84)) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* @notice Retrieve fromChainId from message data. | ||
* @return _msgDataFromChainId ID of the chain that dispatched the messages | ||
*/ | ||
function _fromChainId() internal pure returns (uint256 _msgDataFromChainId) { | ||
_msgDataFromChainId; | ||
|
||
if (msg.data.length >= 52) { | ||
assembly { | ||
_msgDataFromChainId := calldataload(sub(calldatasize(), 52)) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* @notice Retrieve signer address from message data. | ||
* @return _signer Address of the signer | ||
*/ | ||
function _msgSender() internal view returns (address payable _signer) { | ||
_signer = payable(msg.sender); | ||
|
||
if (msg.data.length >= 20 && isTrustedExecutor(_signer)) { | ||
assembly { | ||
_signer := shr(96, calldataload(sub(calldatasize(), 20))) | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.