mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
commit
a19ed504e5
17
contracts/arbitrum/connectors/hop/events.sol
Normal file
17
contracts/arbitrum/connectors/hop/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogBridge(
|
||||
address token,
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 bonderFee,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
uint256 destinationAmountOutMin,
|
||||
uint256 destinationDeadline,
|
||||
uint256 getId
|
||||
);
|
||||
}
|
52
contracts/arbitrum/connectors/hop/helpers.sol
Normal file
52
contracts/arbitrum/connectors/hop/helpers.sol
Normal file
|
@ -0,0 +1,52 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { DSMath } from "../../common/math.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
import "./interface.sol";
|
||||
|
||||
contract Helpers is DSMath, Basic {
|
||||
/**
|
||||
* @param token The address of token to be bridged.(For USDC: 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174)
|
||||
* @param targetChainId The Id of the destination chain.(For MAINNET : 1)
|
||||
* @param router The address of hop router.
|
||||
* @param recipient The address to recieve the token on destination chain.
|
||||
* @param amount The total amount sent by user (Includes bonder fee, destination chain Tx cost).
|
||||
* @param bonderFee The fee to be recieved by bonder at destination chain.
|
||||
* @param sourceAmountOutMin minimum amount of token out for swap on source chain.
|
||||
* @param sourceDeadline The deadline for the source chain transaction (Recommended - Date.now() + 604800 (1 week))
|
||||
* @param destinationAmountOutMin minimum amount of token out for bridge on target chain, zero for L1 bridging
|
||||
* @param destinationDeadline The deadline for the target chain transaction (Recommended - Date.now() + 604800 (1 week)), zero for L1 bridging
|
||||
*/
|
||||
struct BridgeParams {
|
||||
address token;
|
||||
address router;
|
||||
address recipient;
|
||||
uint256 targetChainId;
|
||||
uint256 amount;
|
||||
uint256 bonderFee;
|
||||
uint256 sourceAmountOutMin;
|
||||
uint256 sourceDeadline;
|
||||
uint256 destinationAmountOutMin;
|
||||
uint256 destinationDeadline;
|
||||
}
|
||||
|
||||
function _swapAndSend(BridgeParams memory params) internal {
|
||||
IHopRouter router = IHopRouter(params.router);
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
approve(tokenContract, params.router, params.amount);
|
||||
|
||||
router.swapAndSend(
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.bonderFee,
|
||||
params.sourceAmountOutMin,
|
||||
params.sourceDeadline,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline
|
||||
);
|
||||
}
|
||||
}
|
17
contracts/arbitrum/connectors/hop/interface.sol
Normal file
17
contracts/arbitrum/connectors/hop/interface.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
||||
interface IHopRouter {
|
||||
function swapAndSend(
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 bonderFee,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
uint256 destinationAmountOutMin,
|
||||
uint256 destinationDeadline
|
||||
) external;
|
||||
}
|
77
contracts/arbitrum/connectors/hop/main.sol
Normal file
77
contracts/arbitrum/connectors/hop/main.sol
Normal file
|
@ -0,0 +1,77 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title Hop.
|
||||
* @dev Cross chain Bridge.
|
||||
*/
|
||||
|
||||
import { TokenInterface, MemoryInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import "./interface.sol";
|
||||
import "./helpers.sol";
|
||||
import "./events.sol";
|
||||
|
||||
abstract contract Resolver is Helpers {
|
||||
/**
|
||||
* @dev Bridge Token.
|
||||
* @notice Bridge Token on HOP.
|
||||
* @param params BridgeParams struct for bridging
|
||||
* @param getId ID to retrieve amount from last spell.
|
||||
*/
|
||||
function bridge(BridgeParams memory params, uint256 getId)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
if (params.targetChainId == 1) {
|
||||
require(
|
||||
params.destinationAmountOutMin == 0,
|
||||
"destinationAmountOutMin != 0, sending to L1"
|
||||
);
|
||||
require(
|
||||
params.destinationDeadline == 0,
|
||||
"destinationDeadline != 0, sending to L1"
|
||||
);
|
||||
}
|
||||
|
||||
params.amount = getUint(getId, params.amount);
|
||||
|
||||
bool isEth = params.token == ethAddr;
|
||||
params.token = params.token == ethAddr ? wethAddr : params.token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
|
||||
if (isEth) {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? address(this).balance
|
||||
: params.amount;
|
||||
convertEthToWeth(isEth, tokenContract, params.amount);
|
||||
} else {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? tokenContract.balanceOf(address(this))
|
||||
: params.amount;
|
||||
}
|
||||
|
||||
_swapAndSend(params);
|
||||
|
||||
_eventName = "LogBridge(address,uint256,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(
|
||||
params.token,
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.bonderFee,
|
||||
params.sourceAmountOutMin,
|
||||
params.sourceDeadline,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline,
|
||||
getId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2HopArbitrum is Resolver {
|
||||
string public constant name = "Hop-v1.0";
|
||||
}
|
14
contracts/mainnet/connectors/hop/events.sol
Normal file
14
contracts/mainnet/connectors/hop/events.sol
Normal file
|
@ -0,0 +1,14 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogBridge(
|
||||
address token,
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
uint256 getId
|
||||
);
|
||||
}
|
45
contracts/mainnet/connectors/hop/helpers.sol
Normal file
45
contracts/mainnet/connectors/hop/helpers.sol
Normal file
|
@ -0,0 +1,45 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { DSMath } from "../../common/math.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
import "./interface.sol";
|
||||
|
||||
contract Helpers is DSMath, Basic {
|
||||
/**
|
||||
* @param token The address of token to be bridged.(For USDC: 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)
|
||||
* @param hopRouter The address of hop l1Bridge.
|
||||
* @param chainId The Id of the destination chain.(For POLYGON : 137)
|
||||
* @param recipient The address to recieve the token on destination chain.
|
||||
* @param amount The total amount sent by user (Includes bonder fee, destination chain Tx cost).
|
||||
* @param amountOutMin minimum amount of token out for swap
|
||||
* @param deadline The deadline for the transaction (Recommended - Date.now() + 604800 (1 week))
|
||||
*/
|
||||
struct BridgeParams {
|
||||
address token;
|
||||
address recipient;
|
||||
address router;
|
||||
uint256 targetChainId;
|
||||
uint256 amount;
|
||||
uint256 destinationAmountOutMin;
|
||||
uint256 destinationDeadline;
|
||||
}
|
||||
|
||||
function _sendToL2(BridgeParams memory params) internal {
|
||||
IHopRouter router = IHopRouter(params.router);
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
approve(tokenContract, params.router, params.amount);
|
||||
|
||||
router.sendToL2(
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline,
|
||||
address(0), // relayer address
|
||||
0 // relayer fee
|
||||
);
|
||||
}
|
||||
}
|
16
contracts/mainnet/connectors/hop/interface.sol
Normal file
16
contracts/mainnet/connectors/hop/interface.sol
Normal file
|
@ -0,0 +1,16 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
||||
interface IHopRouter {
|
||||
function sendToL2(
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
address relayer,
|
||||
uint256 relayerFee
|
||||
) external;
|
||||
}
|
63
contracts/mainnet/connectors/hop/main.sol
Normal file
63
contracts/mainnet/connectors/hop/main.sol
Normal file
|
@ -0,0 +1,63 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title Hop.
|
||||
* @dev Cross chain Bridge.
|
||||
*/
|
||||
|
||||
import { TokenInterface, MemoryInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import "./interface.sol";
|
||||
import "./helpers.sol";
|
||||
import "./events.sol";
|
||||
|
||||
abstract contract Resolver is Helpers {
|
||||
/**
|
||||
* @dev Bridge Token.
|
||||
* @notice Bridge Token on HOP.
|
||||
* @param params BridgeParams struct for bridging
|
||||
* @param getId ID to retrieve amount from last spell.
|
||||
*/
|
||||
function bridge(BridgeParams memory params, uint256 getId)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
params.amount = getUint(getId, params.amount);
|
||||
|
||||
bool isEth = params.token == ethAddr;
|
||||
params.token = params.token == ethAddr ? wethAddr : params.token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
|
||||
if (isEth) {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? address(this).balance
|
||||
: params.amount;
|
||||
convertEthToWeth(isEth, tokenContract, params.amount);
|
||||
} else {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? tokenContract.balanceOf(address(this))
|
||||
: params.amount;
|
||||
}
|
||||
|
||||
_sendToL2(params);
|
||||
|
||||
_eventName = "LogBridge(address,uint256,address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(
|
||||
params.token,
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline,
|
||||
getId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2Hop is Resolver {
|
||||
string public constant name = "Hop-v1.0";
|
||||
}
|
17
contracts/optimism/connectors/hop/events.sol
Normal file
17
contracts/optimism/connectors/hop/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogBridge(
|
||||
address token,
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 bonderFee,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
uint256 destinationAmountOutMin,
|
||||
uint256 destinationDeadline,
|
||||
uint256 getId
|
||||
);
|
||||
}
|
52
contracts/optimism/connectors/hop/helpers.sol
Normal file
52
contracts/optimism/connectors/hop/helpers.sol
Normal file
|
@ -0,0 +1,52 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { DSMath } from "../../common/math.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
import "./interface.sol";
|
||||
|
||||
contract Helpers is DSMath, Basic {
|
||||
/**
|
||||
* @param token The address of token to be bridged.(For USDC: 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174)
|
||||
* @param targetChainId The Id of the destination chain.(For MAINNET : 1)
|
||||
* @param router The address of hop router.
|
||||
* @param recipient The address to recieve the token on destination chain.
|
||||
* @param amount The total amount sent by user (Includes bonder fee, destination chain Tx cost).
|
||||
* @param bonderFee The fee to be recieved by bonder at destination chain.
|
||||
* @param sourceAmountOutMin minimum amount of token out for swap on source chain.
|
||||
* @param sourceDeadline The deadline for the source chain transaction (Recommended - Date.now() + 604800 (1 week))
|
||||
* @param destinationAmountOutMin minimum amount of token out for bridge on target chain, zero for L1 bridging
|
||||
* @param destinationDeadline The deadline for the target chain transaction (Recommended - Date.now() + 604800 (1 week)), zero for L1 bridging
|
||||
*/
|
||||
struct BridgeParams {
|
||||
address token;
|
||||
address router;
|
||||
address recipient;
|
||||
uint256 targetChainId;
|
||||
uint256 amount;
|
||||
uint256 bonderFee;
|
||||
uint256 sourceAmountOutMin;
|
||||
uint256 sourceDeadline;
|
||||
uint256 destinationAmountOutMin;
|
||||
uint256 destinationDeadline;
|
||||
}
|
||||
|
||||
function _swapAndSend(BridgeParams memory params) internal {
|
||||
IHopRouter router = IHopRouter(params.router);
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
approve(tokenContract, params.router, params.amount);
|
||||
|
||||
router.swapAndSend(
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.bonderFee,
|
||||
params.sourceAmountOutMin,
|
||||
params.sourceDeadline,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline
|
||||
);
|
||||
}
|
||||
}
|
17
contracts/optimism/connectors/hop/interface.sol
Normal file
17
contracts/optimism/connectors/hop/interface.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
||||
interface IHopRouter {
|
||||
function swapAndSend(
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 bonderFee,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
uint256 destinationAmountOutMin,
|
||||
uint256 destinationDeadline
|
||||
) external;
|
||||
}
|
77
contracts/optimism/connectors/hop/main.sol
Normal file
77
contracts/optimism/connectors/hop/main.sol
Normal file
|
@ -0,0 +1,77 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title Hop.
|
||||
* @dev Cross chain Bridge.
|
||||
*/
|
||||
|
||||
import { TokenInterface, MemoryInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import "./interface.sol";
|
||||
import "./helpers.sol";
|
||||
import "./events.sol";
|
||||
|
||||
abstract contract Resolver is Helpers {
|
||||
/**
|
||||
* @dev Bridge Token.
|
||||
* @notice Bridge Token on HOP.
|
||||
* @param params BridgeParams struct for bridging
|
||||
* @param getId ID to retrieve amount from last spell.
|
||||
*/
|
||||
function bridge(BridgeParams memory params, uint256 getId)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
if (params.targetChainId == 1) {
|
||||
require(
|
||||
params.destinationAmountOutMin == 0,
|
||||
"destinationAmountOutMin != 0, sending to L1"
|
||||
);
|
||||
require(
|
||||
params.destinationDeadline == 0,
|
||||
"destinationDeadline != 0, sending to L1"
|
||||
);
|
||||
}
|
||||
|
||||
params.amount = getUint(getId, params.amount);
|
||||
|
||||
bool isEth = params.token == ethAddr;
|
||||
params.token = params.token == ethAddr ? wethAddr : params.token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
|
||||
if (isEth) {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? address(this).balance
|
||||
: params.amount;
|
||||
convertEthToWeth(isEth, tokenContract, params.amount);
|
||||
} else {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? tokenContract.balanceOf(address(this))
|
||||
: params.amount;
|
||||
}
|
||||
|
||||
_swapAndSend(params);
|
||||
|
||||
_eventName = "LogBridge(address,uint256,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(
|
||||
params.token,
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.bonderFee,
|
||||
params.sourceAmountOutMin,
|
||||
params.sourceDeadline,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline,
|
||||
getId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2HopOptimism is Resolver {
|
||||
string public constant name = "Hop-v1.0";
|
||||
}
|
17
contracts/polygon/connectors/hop/events.sol
Normal file
17
contracts/polygon/connectors/hop/events.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
contract Events {
|
||||
event LogBridge(
|
||||
address token,
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 bonderFee,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
uint256 destinationAmountOutMin,
|
||||
uint256 destinationDeadline,
|
||||
uint256 getId
|
||||
);
|
||||
}
|
52
contracts/polygon/connectors/hop/helpers.sol
Normal file
52
contracts/polygon/connectors/hop/helpers.sol
Normal file
|
@ -0,0 +1,52 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
import { DSMath } from "../../common/math.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
import "./interface.sol";
|
||||
|
||||
contract Helpers is DSMath, Basic {
|
||||
/**
|
||||
* @param token The address of token to be bridged.(For USDC: 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174)
|
||||
* @param targetChainId The Id of the destination chain.(For MAINNET : 1)
|
||||
* @param router The address of hop router.
|
||||
* @param recipient The address to recieve the token on destination chain.
|
||||
* @param amount The total amount sent by user (Includes bonder fee, destination chain Tx cost).
|
||||
* @param bonderFee The fee to be recieved by bonder at destination chain.
|
||||
* @param sourceAmountOutMin minimum amount of token out for swap on source chain.
|
||||
* @param sourceDeadline The deadline for the source chain transaction (Recommended - Date.now() + 604800 (1 week))
|
||||
* @param destinationAmountOutMin minimum amount of token out for bridge on target chain, zero for L1 bridging
|
||||
* @param destinationDeadline The deadline for the target chain transaction (Recommended - Date.now() + 604800 (1 week)), zero for L1 bridging
|
||||
*/
|
||||
struct BridgeParams {
|
||||
address token;
|
||||
address router;
|
||||
address recipient;
|
||||
uint256 targetChainId;
|
||||
uint256 amount;
|
||||
uint256 bonderFee;
|
||||
uint256 sourceAmountOutMin;
|
||||
uint256 sourceDeadline;
|
||||
uint256 destinationAmountOutMin;
|
||||
uint256 destinationDeadline;
|
||||
}
|
||||
|
||||
function _swapAndSend(BridgeParams memory params) internal {
|
||||
IHopRouter router = IHopRouter(params.router);
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
approve(tokenContract, params.router, params.amount);
|
||||
|
||||
router.swapAndSend(
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.bonderFee,
|
||||
params.sourceAmountOutMin,
|
||||
params.sourceDeadline,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline
|
||||
);
|
||||
}
|
||||
}
|
17
contracts/polygon/connectors/hop/interface.sol
Normal file
17
contracts/polygon/connectors/hop/interface.sol
Normal file
|
@ -0,0 +1,17 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
||||
interface IHopRouter {
|
||||
function swapAndSend(
|
||||
uint256 chainId,
|
||||
address recipient,
|
||||
uint256 amount,
|
||||
uint256 bonderFee,
|
||||
uint256 amountOutMin,
|
||||
uint256 deadline,
|
||||
uint256 destinationAmountOutMin,
|
||||
uint256 destinationDeadline
|
||||
) external;
|
||||
}
|
77
contracts/polygon/connectors/hop/main.sol
Normal file
77
contracts/polygon/connectors/hop/main.sol
Normal file
|
@ -0,0 +1,77 @@
|
|||
//SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.7.0;
|
||||
pragma experimental ABIEncoderV2;
|
||||
|
||||
/**
|
||||
* @title Hop.
|
||||
* @dev Cross chain Bridge.
|
||||
*/
|
||||
|
||||
import { TokenInterface, MemoryInterface } from "../../common/interfaces.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import "./interface.sol";
|
||||
import "./helpers.sol";
|
||||
import "./events.sol";
|
||||
|
||||
abstract contract Resolver is Helpers {
|
||||
/**
|
||||
* @dev Bridge Token.
|
||||
* @notice Bridge Token on HOP.
|
||||
* @param params BridgeParams struct for bridging
|
||||
* @param getId ID to retrieve amount from last spell.
|
||||
*/
|
||||
function bridge(BridgeParams memory params, uint256 getId)
|
||||
external
|
||||
payable
|
||||
returns (string memory _eventName, bytes memory _eventParam)
|
||||
{
|
||||
if (params.targetChainId == 1) {
|
||||
require(
|
||||
params.destinationAmountOutMin == 0,
|
||||
"destinationAmountOutMin != 0, sending to L1"
|
||||
);
|
||||
require(
|
||||
params.destinationDeadline == 0,
|
||||
"destinationDeadline != 0, sending to L1"
|
||||
);
|
||||
}
|
||||
|
||||
params.amount = getUint(getId, params.amount);
|
||||
|
||||
bool isMatic = params.token == maticAddr;
|
||||
params.token = params.token == maticAddr ? wmaticAddr : params.token;
|
||||
|
||||
TokenInterface tokenContract = TokenInterface(params.token);
|
||||
|
||||
if (isMatic) {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? address(this).balance
|
||||
: params.amount;
|
||||
convertMaticToWmatic(isMatic, tokenContract, params.amount);
|
||||
} else {
|
||||
params.amount = params.amount == uint256(-1)
|
||||
? tokenContract.balanceOf(address(this))
|
||||
: params.amount;
|
||||
}
|
||||
|
||||
_swapAndSend(params);
|
||||
|
||||
_eventName = "LogBridge(address,uint256,address,uint256,uint256,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(
|
||||
params.token,
|
||||
params.targetChainId,
|
||||
params.recipient,
|
||||
params.amount,
|
||||
params.bonderFee,
|
||||
params.sourceAmountOutMin,
|
||||
params.sourceDeadline,
|
||||
params.destinationAmountOutMin,
|
||||
params.destinationDeadline,
|
||||
getId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
contract ConnectV2HopPolygon is Resolver {
|
||||
string public constant name = "Hop-v1.0";
|
||||
}
|
240
test/polygon/hop/hop.test.ts
Normal file
240
test/polygon/hop/hop.test.ts
Normal file
|
@ -0,0 +1,240 @@
|
|||
import { expect } from "chai";
|
||||
import hre from "hardhat";
|
||||
const { waffle, ethers } = hre;
|
||||
const { provider } = waffle;
|
||||
|
||||
import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector";
|
||||
import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2";
|
||||
import { encodeSpells } from "../../../scripts/tests/encodeSpells";
|
||||
import { getMasterSigner } from "../../../scripts/tests/getMasterSigner";
|
||||
import { addLiquidity } from "../../../scripts/tests/addLiquidity";
|
||||
import { addresses } from "../../../scripts/tests/polygon/addresses";
|
||||
import { abis } from "../../../scripts/constant/abis";
|
||||
import { ConnectV2HopPolygon__factory } from "../../../typechain";
|
||||
import { Signer, Contract } from "ethers";
|
||||
import BigNumber from "bignumber.js";
|
||||
|
||||
describe("Hop Connector", function () {
|
||||
const connectorName = "HOP-A";
|
||||
|
||||
let dsaWallet0: Contract;
|
||||
let masterSigner: Signer;
|
||||
let instaConnectorsV2: Contract;
|
||||
let connector: Contract;
|
||||
let latestBlock: any;
|
||||
|
||||
const wallets = provider.getWallets();
|
||||
const [wallet0, wallet1, wallet2, wallet3] = wallets;
|
||||
|
||||
const saddleSwapABI = [
|
||||
{
|
||||
inputs: [{ internalType: "address", name: "tokenAddress", type: "address" }],
|
||||
name: "getTokenIndex",
|
||||
outputs: [{ internalType: "uint8", name: "", type: "uint8" }],
|
||||
stateMutability: "view",
|
||||
type: "function"
|
||||
},
|
||||
{
|
||||
inputs: [
|
||||
{ internalType: "uint8", name: "tokenIndexFrom", type: "uint8" },
|
||||
{ internalType: "uint8", name: "tokenIndexTo", type: "uint8" },
|
||||
{ internalType: "uint256", name: "dx", type: "uint256" }
|
||||
],
|
||||
name: "calculateSwap",
|
||||
outputs: [{ internalType: "uint256", name: "", type: "uint256" }],
|
||||
stateMutability: "view",
|
||||
type: "function"
|
||||
}
|
||||
];
|
||||
|
||||
const l2BridgeABI = [
|
||||
{
|
||||
anonymous: false,
|
||||
inputs: [
|
||||
{ indexed: true, internalType: "bytes32", name: "transferId", type: "bytes32" },
|
||||
{ indexed: true, internalType: "uint256", name: "chainId", type: "uint256" },
|
||||
{ indexed: true, internalType: "address", name: "recipient", type: "address" },
|
||||
{ indexed: false, internalType: "uint256", name: "amount", type: "uint256" },
|
||||
{ indexed: false, internalType: "bytes32", name: "transferNonce", type: "bytes32" },
|
||||
{ indexed: false, internalType: "uint256", name: "bonderFee", type: "uint256" },
|
||||
{ indexed: false, internalType: "uint256", name: "index", type: "uint256" },
|
||||
{ indexed: false, internalType: "uint256", name: "amountOutMin", type: "uint256" },
|
||||
{ indexed: false, internalType: "uint256", name: "deadline", type: "uint256" }
|
||||
],
|
||||
name: "TransferSent",
|
||||
type: "event"
|
||||
}
|
||||
];
|
||||
|
||||
const DAI_ADDR = "0x8f3cf7ad23cd3cadbd9735aff958023239c6a063";
|
||||
const hDai = "0xb8901acB165ed027E32754E0FFe830802919727f";
|
||||
const l2AmmWrapper = "0x28529fec439cfF6d7D1D5917e956dEE62Cd3BE5c";
|
||||
const l2Bridge = "0xEcf268Be00308980B5b3fcd0975D47C4C8e1382a";
|
||||
const saddleSwap = "0x25FB92E505F752F730cAD0Bd4fa17ecE4A384266";
|
||||
const saddleSwapInstance = new ethers.Contract(saddleSwap, saddleSwapABI);
|
||||
|
||||
const token = new ethers.Contract(DAI_ADDR, abis.basic.erc20);
|
||||
const l2BridgeInstance = new ethers.Contract(l2Bridge, l2BridgeABI);
|
||||
|
||||
before(async () => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
// @ts-ignore
|
||||
jsonRpcUrl: hre.config.networks.hardhat.forking.url,
|
||||
blockNumber: 27054896
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
masterSigner = await getMasterSigner();
|
||||
instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2);
|
||||
connector = await deployAndEnableConnector({
|
||||
connectorName,
|
||||
contractArtifact: ConnectV2HopPolygon__factory,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2
|
||||
});
|
||||
console.log("Connector address", connector.address);
|
||||
});
|
||||
|
||||
it("Should have contracts deployed.", async function () {
|
||||
expect(!!instaConnectorsV2.address).to.be.true;
|
||||
expect(!!connector.address).to.be.true;
|
||||
expect(!!(await masterSigner.getAddress())).to.be.true;
|
||||
});
|
||||
|
||||
describe("DSA wallet setup", function () {
|
||||
it("Should build DSA v2", async function () {
|
||||
dsaWallet0 = await buildDSAv2(wallet0.address);
|
||||
expect(!!dsaWallet0.address).to.be.true;
|
||||
});
|
||||
|
||||
it("Deposit MATIC & DAI into DSA wallet", async function () {
|
||||
await wallet0.sendTransaction({
|
||||
to: dsaWallet0.address,
|
||||
value: ethers.utils.parseEther("10")
|
||||
});
|
||||
expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte(ethers.utils.parseEther("10"));
|
||||
|
||||
await addLiquidity("dai", dsaWallet0.address, ethers.utils.parseEther("10000"));
|
||||
});
|
||||
});
|
||||
|
||||
describe("Main", function () {
|
||||
it("should migrate from L2 to L1", async function () {
|
||||
const amount = ethers.utils.parseEther("10");
|
||||
const bonderFee = new BigNumber(100 * 1e9)
|
||||
.multipliedBy(150000)
|
||||
.multipliedBy(1.5)
|
||||
.plus(new BigNumber(amount.toString()).multipliedBy(0.18));
|
||||
const deadline = Date.now() + 604800;
|
||||
const getId = "0";
|
||||
|
||||
await token.connect(wallet0).approve(l2AmmWrapper, amount.toString());
|
||||
|
||||
const hDaiIdx = await saddleSwapInstance.connect(wallet0).getTokenIndex(hDai);
|
||||
const daiIdx = await saddleSwapInstance.connect(wallet0).getTokenIndex(DAI_ADDR);
|
||||
|
||||
let amountOutMin = await saddleSwapInstance.connect(wallet0).calculateSwap(daiIdx, hDaiIdx, amount.toString());
|
||||
amountOutMin = new BigNumber(amountOutMin.toString()).multipliedBy(0.99);
|
||||
|
||||
const params: any = [
|
||||
DAI_ADDR,
|
||||
l2AmmWrapper,
|
||||
wallet0.address,
|
||||
1,
|
||||
amount.toString(),
|
||||
bonderFee.toString(),
|
||||
amountOutMin.toFixed(0),
|
||||
deadline,
|
||||
"0",
|
||||
"0"
|
||||
];
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "bridge",
|
||||
args: [params, getId]
|
||||
}
|
||||
];
|
||||
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
|
||||
let receipt = await tx.wait();
|
||||
latestBlock = receipt.blockNumber;
|
||||
});
|
||||
|
||||
it("Should fetch transferId from TransferSent Event", async function () {
|
||||
const filter = l2BridgeInstance.connect(wallet0).filters.TransferSent();
|
||||
const events = await l2BridgeInstance.connect(wallet0).queryFilter(filter, 27054896, latestBlock);
|
||||
|
||||
const transferSentEvent: any = events[0].args;
|
||||
|
||||
expect(transferSentEvent[2].toLowerCase()).to.be.equals(wallet0.address.toLowerCase());
|
||||
console.log("TransferId", transferSentEvent[0]);
|
||||
});
|
||||
|
||||
it("should migrate from L2 to L2", async function () {
|
||||
const amount = ethers.utils.parseEther("10");
|
||||
|
||||
const hDaiIdx = await saddleSwapInstance.connect(wallet0).getTokenIndex(hDai);
|
||||
const daiIdx = await saddleSwapInstance.connect(wallet0).getTokenIndex(DAI_ADDR);
|
||||
|
||||
let destinationAmountOutMin = await saddleSwapInstance
|
||||
.connect(wallet0)
|
||||
.calculateSwap(hDaiIdx, daiIdx, amount.toString());
|
||||
destinationAmountOutMin = new BigNumber(destinationAmountOutMin.toString()).multipliedBy(0.99);
|
||||
|
||||
let amountOutMin = await saddleSwapInstance.connect(wallet0).calculateSwap(daiIdx, hDaiIdx, amount.toString());
|
||||
amountOutMin = new BigNumber(amountOutMin.toString()).multipliedBy(0.99);
|
||||
|
||||
const bonderFee = new BigNumber(1e9)
|
||||
.multipliedBy(150000)
|
||||
.multipliedBy(1.5)
|
||||
.plus(new BigNumber(amount.toString()).multipliedBy(0.18));
|
||||
const deadline = Date.now() + 604800;
|
||||
const getId = "0";
|
||||
|
||||
await token.connect(wallet0).approve(l2AmmWrapper, amount.toString());
|
||||
|
||||
const params: any = [
|
||||
DAI_ADDR,
|
||||
l2AmmWrapper,
|
||||
wallet0.address,
|
||||
10,
|
||||
amount.toString(),
|
||||
bonderFee.toString(),
|
||||
amountOutMin.toFixed(0),
|
||||
deadline,
|
||||
destinationAmountOutMin.toFixed(0),
|
||||
deadline
|
||||
];
|
||||
|
||||
const spells = [
|
||||
{
|
||||
connector: connectorName,
|
||||
method: "bridge",
|
||||
args: [params, getId]
|
||||
}
|
||||
];
|
||||
|
||||
const tx = await dsaWallet0.connect(wallet0).cast(...encodeSpells(spells), wallet1.address);
|
||||
let receipt = await tx.wait();
|
||||
latestBlock = receipt.blockNumber;
|
||||
});
|
||||
|
||||
it("Should fetch transferId from TransferSent Event", async function () {
|
||||
const filter = l2BridgeInstance.connect(wallet0).filters.TransferSent();
|
||||
const events = await l2BridgeInstance.connect(wallet0).queryFilter(filter, 27054896, latestBlock);
|
||||
|
||||
const transferSentEvent: any = events[1].args;
|
||||
|
||||
expect(transferSentEvent[2].toLowerCase()).to.be.equals(wallet0.address.toLowerCase());
|
||||
console.log("TransferId", transferSentEvent[0]);
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user