Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Warp Route Wrapper Contract for Hyperlane #31

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
72 changes: 72 additions & 0 deletions src/helper/WarpRouteWrapper.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.21;

import { ERC20 } from "@solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "@solmate/utils/SafeTransferLib.sol";
import { BoringVault } from "../base/BoringVault.sol";
import { TellerWithMultiAssetSupport } from "../base/Roles/TellerWithMultiAssetSupport.sol";

interface WarpRoute {
function transferRemote(uint32 _destination, bytes32 _recipient, uint256 _amountOrId) external returns (bytes32);
}

/**
* @notice A simple wrapper to call both `deposit` on a Teller and
* `transferRemote` on a WarpRoute in one transaction. This contract can only be
* used with a defined Teller. If a new Teller is deployed, a new Wrapper must
* be deployed.
*/
junkim012 marked this conversation as resolved.
Show resolved Hide resolved
contract WarpRouteWrapper {
using SafeTransferLib for ERC20;

error InvalidDestination();

BoringVault public boringVault;
TellerWithMultiAssetSupport public teller;
WarpRoute public warpRoute;
uint32 public destination;

constructor(TellerWithMultiAssetSupport _teller, WarpRoute _warpRoute, uint32 _destination) {
teller = _teller;
warpRoute = _warpRoute;
destination = _destination;

boringVault = _teller.vault();

// Infinite approvals to the warpRoute okay because this contract will
// never hold any balance aside from donations.
boringVault.approve(address(warpRoute), type(uint256).max);
}

/**
* @dev There's two sets of approvals this contract needs to grant. It needs
* to approve the BoringVault to take its `depositAsset`, and it needs to
* approve the WarpRoute to take the BoringVault shares. The latter is done
* in the constructor.
*
* NOTE that the `depositAsset` can vary as the Teller can add new supported
* assets.
*/
function depositAndBridge(
ERC20 depositAsset,
uint256 depositAmount,
uint256 minimumMint,
uint32 _destination,
junkim012 marked this conversation as resolved.
Show resolved Hide resolved
bytes32 _recipient
)
external
returns (uint256 sharesMinted, bytes32 messageId)
{
if (_destination != destination) revert InvalidDestination();
junkim012 marked this conversation as resolved.
Show resolved Hide resolved

depositAsset.safeTransferFrom(msg.sender, address(this), depositAmount);

if (depositAsset.allowance(address(this), address(boringVault)) < depositAmount) {
depositAsset.approve(address(boringVault), type(uint256).max);
}

sharesMinted = teller.deposit(depositAsset, depositAmount, minimumMint);

messageId = warpRoute.transferRemote(_destination, _recipient, sharesMinted);
}
}
Loading