Skip to content

Commit

Permalink
Draft implementation of the L2BitcoinDepositor contract
Browse files Browse the repository at this point in the history
Here we present a draft implementation of the `L2BitcoinDepositor` contract
that acts as an entrypoint of the tBTC direct bridging feature on the given
L2 chain. This contract exposes the `revealDeposit` function that takes the
deposit data (funding tx, reveal info, original depositor) and relays it to the
`L1BitcoinDepositor` contract using the Wormhole Relayer infrastructure.
  • Loading branch information
lukasz-zimnoch committed Feb 28, 2024
1 parent 9e047d1 commit 9583e66
Showing 1 changed file with 139 additions and 0 deletions.
139 changes: 139 additions & 0 deletions solidity/contracts/l2/L2BitcoinDepositor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// SPDX-License-Identifier: GPL-3.0-only

// ██████████████ ▐████▌ ██████████████
// ██████████████ ▐████▌ ██████████████
// ▐████▌ ▐████▌
// ▐████▌ ▐████▌
// ██████████████ ▐████▌ ██████████████
// ██████████████ ▐████▌ ██████████████
// ▐████▌ ▐████▌
// ▐████▌ ▐████▌
// ▐████▌ ▐████▌
// ▐████▌ ▐████▌
// ▐████▌ ▐████▌
// ▐████▌ ▐████▌

pragma solidity ^0.8.17;

import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";

import "../integrator/IBridge.sol";

/// @title IWormholeRelayer
/// @notice Wormhole Relayer interface. Contains only selected functions
/// used by L2BitcoinDepositor.
/// @dev See: https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/2b7db51f99b49eda99b44f4a044e751cb0b2e8ea/src/interfaces/IWormholeRelayer.sol#L74
interface IWormholeRelayer {
/// @dev See: https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/2b7db51f99b49eda99b44f4a044e751cb0b2e8ea/src/interfaces/IWormholeRelayer.sol#L122
function sendPayloadToEvm(
uint16 targetChain,
address targetAddress,
bytes memory payload,
uint256 receiverValue,
uint256 gasLimit,
uint16 refundChain,
address refundAddress
) external payable returns (uint64 sequence);

/// @dev See: https://github.com/wormhole-foundation/wormhole-solidity-sdk/blob/2b7db51f99b49eda99b44f4a044e751cb0b2e8ea/src/interfaces/IWormholeRelayer.sol#L442
function quoteEVMDeliveryPrice(
uint16 targetChain,
uint256 receiverValue,
uint256 gasLimit
)
external
view
returns (
uint256 nativePriceQuote,
uint256 targetChainRefundPerGasUnused
);
}

// TODO: Document this contract.
contract L2BitcoinDepositor is OwnableUpgradeable {
// TODO: Document state variables.
IWormholeRelayer public wormholeRelayer;
uint16 public l2ChainId;
uint16 public l1ChainId;
address public l1BitcoinDepositor;
uint256 public l1RevealDepositGasLimit;

event DepositRevealed(
bytes32 payloadHash,
uint64 sequence,
address indexed depositor,
address indexed sender
);

event L1RevealDepositGasLimitUpdated(uint256 l1RevealDepositGasLimit);

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function initialize(
address _wormholeRelayer,
uint16 _l2ChainId,
uint16 _l1ChainId,
address _l1BitcoinDepositor
) external initializer {
__Ownable_init();

wormholeRelayer = IWormholeRelayer(_wormholeRelayer);
l2ChainId = _l2ChainId;
l1ChainId = _l1ChainId;
l1BitcoinDepositor = _l1BitcoinDepositor;
l1RevealDepositGasLimit = 200_000;
}

// TODO: Document this function.
function updateL1RevealDepositGasLimit(uint256 _l1RevealDepositGasLimit)
external
onlyOwner
{
l1RevealDepositGasLimit = _l1RevealDepositGasLimit;
emit L1RevealDepositGasLimitUpdated(_l1RevealDepositGasLimit);
}

// TODO: Document this function.
function revealDeposit(
IBridgeTypes.BitcoinTxInfo calldata fundingTx,
IBridgeTypes.DepositRevealInfo calldata reveal,
address depositor
) external payable {
// Cost of requesting a `revealDeposit` message to be sent to `l1Chain`
// with a gasLimit of `l1RevealDepositGasLimit`.
uint256 cost = quoteRevealDeposit();

require(msg.value == cost, "Payment for Wormhole relayer is too low");

bytes memory payload = abi.encode(fundingTx, reveal, depositor);

uint64 sequence = wormholeRelayer.sendPayloadToEvm{value: cost}(
l1ChainId,
l1BitcoinDepositor,
payload,
0, // No receiver value needed.
l1RevealDepositGasLimit,
l2ChainId, // Set this L2 chain as the refund chain.
msg.sender // Set the caller as the refund receiver.
);

emit DepositRevealed(
keccak256(payload),
sequence,
depositor,
msg.sender
);
}

// TODO: Document this function.
function quoteRevealDeposit() public view returns (uint256 cost) {
(cost, ) = wormholeRelayer.quoteEVMDeliveryPrice(
l1ChainId,
0, // No receiver value needed.
l1RevealDepositGasLimit
);
}
}

0 comments on commit 9583e66

Please sign in to comment.