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

zksync #78

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ AURORA_RPC="https://mainnet.aurora.dev"
DOGECHAIN_PK_DEPLOYER="1111111111111111111111111111111111111111111111111111111111111111"
DOGECHAIN_RPC="https://rpc01-sg.dogechain.dog"

ZKSYNC_PK_DEPLOYER="1111111111111111111111111111111111111111111111111111111111111111"
ZKSYNC_RPC="https://mainnet.era.zksync.io"
ZKSYNC_VERIFY_URL="https://zksync2-mainnet-explorer.zksync.io/contract_verification"

ETHEREUM_MAINNET_RPC="https://eth.llamarpc.com"


ETHERSCAN_API_KEY="UEPS5EZJFNJM3N8GEMAJKZMTSYAAY8X1FP"
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package-lock.json
node_modules
playground
artifacts
artifacts-zk
.DS_Store
.scripts
.vscode
cache
cache-zk
.env
out
.vscode
31 changes: 30 additions & 1 deletion hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,13 @@ require('hardhat-deploy-ethers');
require('hardhat-abi-exporter');
require("hardhat-gas-reporter");
require('hardhat-log-remover');
require("hardhat-tracer");
require('hardhat-deploy');
require("hardhat-tracer");
require("@matterlabs/hardhat-zksync-deploy");
require("@matterlabs/hardhat-zksync-solc");
require("@matterlabs/hardhat-zksync-toolbox");
require("@matterlabs/hardhat-zksync-verify");


// Tasks
require('./src/tasks/update-hop-tokens')
Expand All @@ -23,11 +28,15 @@ const ARBITRUM_RPC = getEnvValSafe('ARBITRUM_RPC')
const OPTIMISM_RPC = getEnvValSafe('OPTIMISM_RPC')
const AURORA_RPC = getEnvValSafe('AURORA_RPC')
const DOGECHAIN_RPC = getEnvValSafe('DOGECHAIN_RPC')
const ZKSYNC_RPC = getEnvValSafe('ZKSYNC_RPC')
const ZKSYNC_VERIFY_URL = getEnvValSafe('ZKSYNC_VERIFY_URL')
const ETHEREUM_MAINNET_RPC = getEnvValSafe('ETHEREUM_MAINNET_RPC')
const AVALANCHE_PK_DEPLOYER = getEnvValSafe('AVALANCHE_PK_DEPLOYER')
const ARBITRUM_PK_DEPLOYER = getEnvValSafe('ARBITRUM_PK_DEPLOYER')
const OPTIMISM_PK_DEPLOYER = getEnvValSafe('OPTIMISM_PK_DEPLOYER')
const AURORA_PK_DEPLOYER = getEnvValSafe('AURORA_PK_DEPLOYER')
const DOGECHAIN_PK_DEPLOYER = getEnvValSafe('DOGECHAIN_PK_DEPLOYER')
const ZKSYNC_PK_DEPLOYER = getEnvValSafe("ZKSYNC_PK_DEPLOYER")
const ETHERSCAN_API_KEY = getEnvValSafe('ETHERSCAN_API_KEY', false)

function getEnvValSafe(key, required=true) {
Expand All @@ -52,6 +61,11 @@ module.exports = {
}
}
},
zksolc: {
version: "1.3.8",
compilerSource: "binary",
settings: {},
},
namedAccounts: {
deployer: {
default: 0,
Expand All @@ -63,6 +77,7 @@ module.exports = {
defaultNetwork: 'hardhat',
networks: {
hardhat: {
zksync: false,
chainId: 43114,
forking: {
url: AVALANCHE_RPC,
Expand All @@ -74,36 +89,50 @@ module.exports = {
}
},
avalanche: {
zksync: false,
chainId: 43114,
gasPrice: 225000000000,
url: AVALANCHE_RPC,
accounts: [ AVALANCHE_PK_DEPLOYER ]
},
fuji: {
zksync: false,
chainId: 43113,
url: FUJI_RPC,
accounts: [ AVALANCHE_PK_DEPLOYER ],
},
arbitrum: {
zksync: false,
chainId: 42161,
url: ARBITRUM_RPC,
accounts: [ ARBITRUM_PK_DEPLOYER ],
},
optimism: {
zksync: false,
chainId: 10,
url: OPTIMISM_RPC,
accounts: [ OPTIMISM_PK_DEPLOYER ],
},
aurora: {
zksync: false,
chainId: 1313161554,
url: AURORA_RPC,
accounts: [ AURORA_PK_DEPLOYER ],
},
dogechain: {
zksync: false,
chainId: 2000,
url: DOGECHAIN_RPC,
accounts: [ DOGECHAIN_PK_DEPLOYER ],
},
zksync: {
zksync: true,
chainId: 324,
url: ZKSYNC_RPC,
ethNetwork: ETHEREUM_MAINNET_RPC,
accounts: [ ZKSYNC_PK_DEPLOYER ],
verifyURL: ZKSYNC_VERIFY_URL,
}
},
paths: {
deployments: './src/deployments',
Expand Down
21 changes: 14 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,26 +21,33 @@
"author": "",
"license": "ISC",
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.2",
"@matterlabs/hardhat-zksync-chai-matchers": "^0.1.2",
"@matterlabs/hardhat-zksync-deploy": "^0.6.3",
"@matterlabs/hardhat-zksync-solc": "^0.3.16",
"@matterlabs/hardhat-zksync-toolbox": "^0.1.1",
"@matterlabs/hardhat-zksync-verify": "^0.1.5",
"@nomicfoundation/hardhat-chai-matchers": "^1.0.6",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@nomiclabs/hardhat-waffle": "^2.0.1",
"@openzeppelin/contracts": "^4.7.3",
"chai": "^4.3.4",
"ethereum-waffle": "^3.3.0",
"ethereumjs-util": "^7.0.10",
"ethers": "^5.1.3",
"hardhat": "^2.12.7",
"ethers": "~5.7.2",
"hardhat": "^2.14.0",
"hardhat-abi-exporter": "^2.2.1",
"hardhat-contract-sizer": "^2.0.3",
"hardhat-deploy": "^0.7.10",
"hardhat-deploy": "^0.11.26",
"hardhat-deploy-ethers": "0.3.0-beta.13",
"hardhat-gas-reporter": "^1.0.4",
"hardhat-log-remover": "^2.0.2",
"husky": "^8.0.1"
"husky": "^8.0.1",
"zksync-web3": "^0.14.3"
},
"dependencies": {
"@nomiclabs/hardhat-etherscan": "^2.1.8",
"@nomiclabs/hardhat-etherscan": "^3.1.7",
"dotenv": "^8.2.0",
"hardhat-tracer": "^1.0.0-alpha.5",
"hardhat-tracer": "^2.2.2",
"minimist": "^1.2.6",
"prettier": "^2.7.1",
"prettier-plugin-solidity": "^1.0.0-beta.24",
Expand Down
3 changes: 2 additions & 1 deletion src/contracts/YakAdapter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ abstract contract YakAdapter is Maintainable {

function recoverAVAX(uint256 _amount) external onlyMaintainer {
require(_amount > 0, "YakAdapter: Nothing to recover");
payable(msg.sender).transfer(_amount);
(bool success, )= msg.sender.call{value: _amount}("");
require(success, "Transfer failed.");
emit Recovered(address(0), _amount);
}

Expand Down
3 changes: 2 additions & 1 deletion src/contracts/YakRouter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ contract YakRouter is Maintainable, Recoverable, IYakRouter {
) internal {
if (address(this) != _to) {
if (_token == NATIVE) {
payable(_to).transfer(_amount);
(bool success, )= _to.call{value: _amount}("");
require(success, "Transfer failed.");
} else {
IERC20(_token).safeTransfer(_to, _amount);
}
Expand Down
105 changes: 105 additions & 0 deletions src/contracts/adapters/SyncSwapAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;

import "../interface/IERC20.sol";
import "../lib/SafeERC20.sol";
import "../YakAdapter.sol";

interface IFactory {
function getPool(address, address) external view returns (address);
}

interface IPair {
function getAmountOut(address, uint, address) external view returns (uint256);

function swap(
bytes calldata data,
address sender,
address callback,
bytes calldata callbackData
) external returns (address token, uint amount);
}

interface IVault {
function deposit(address token, address to) external returns (uint amount);
}

contract SyncSwapAdapter is YakAdapter {
using SafeERC20 for IERC20;

uint8 constant WITHDRAW_MODE = 2; // receive WETH

address immutable FACTORY;
address immutable STABLE_FACTORY;
address immutable VAULT;

constructor(
string memory _name,
address _factory,
address _stableFactory,
address _vault,
uint256 _swapGasEstimate
) YakAdapter(_name, _swapGasEstimate) {
FACTORY = _factory;
STABLE_FACTORY = _stableFactory;
VAULT = _vault;
}

function _getQuoteAndPair(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) internal view returns (uint256 amountOut, address pair) {
pair = IFactory(FACTORY).getPool(_tokenIn, _tokenOut);
if (pair > address(0)) amountOut = IPair(pair).getAmountOut(_tokenIn, _amountIn, address(this));

address stablePair = IFactory(STABLE_FACTORY).getPool(_tokenIn, _tokenOut);
if (stablePair > address(0)) {
uint256 amountOutStable = IPair(stablePair).getAmountOut(_tokenIn, _amountIn, address(this));
if (amountOutStable > amountOut) {
amountOut = amountOutStable;
pair = stablePair;
}
}
}

function _query(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) internal view override returns (uint256 amountOut) {
if (_tokenIn != _tokenOut && _amountIn != 0) (amountOut, ) = _getQuoteAndPair(_amountIn, _tokenIn, _tokenOut);
}

function _swap(
uint256 _amountIn,
uint256 _amountOut,
address _tokenIn,
address _tokenOut,
address _to
) internal override {
(uint256 amountOut, address pair) = _getQuoteAndPair(_amountIn, _tokenIn, _tokenOut);
require(amountOut >= _amountOut, "Insufficent amount out");
IERC20(_tokenIn).safeTransfer(VAULT, _amountIn);
IVault(VAULT).deposit(_tokenIn, pair);
bytes memory data = abi.encode(_tokenIn, _to, WITHDRAW_MODE);
IPair(pair).swap(data, address(this), address(0), "");
}
}
96 changes: 96 additions & 0 deletions src/contracts/adapters/VelocoreAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// ╟╗ ╔╬
// ╞╬╬ ╬╠╬
// ╔╣╬╬╬ ╠╠╠╠╦
// ╬╬╬╬╬╩ ╘╠╠╠╠╬
// ║╬╬╬╬╬ ╘╠╠╠╠╬
// ╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╬╬╬╬╬╬╬╜ ╠╠╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╠
// ╙╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╕ ╬╬╬╬╬╬╬╜ ╣╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╬╬╬╬╬╬╬╬╬╠╠╠╠╠╠╠╩
// ╙╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╔╬╬╬╬╬╬╬ ╔╠╠╠╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬╬╬╬╬╠╠╠╠╝╙
// ╘╣╬╬╬╬╬╬╬╬╬╬╬╬╬╬ ╒╠╠╠╬╠╬╩╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╣╬╬╬╬╬╬╬╙
// ╣╬╬╬╬╬╬╬╬╬╬╠╣ ╣╬╠╠╠╬╩ ╚╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╣╬╬╬╬╬╬╬╬╬╣ ╣╬╠╠╠╬╬ ╣╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╬╬╬╬╬╬╬
// ╟╬╬╬╬╬╬╬╩ ╬╬╠╠╠╠╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬╠╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╒╬╬╠╠╬╠╠╬╬╬╬╬╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╣╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╬╬╬╠╠╠╠╝╝╝╝╝╝╝╠╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╚╬╬╬╬╬╬╬╬
// ╬╬╬╬╬╬╬ ╣╬╬╬╬╠╠╩ ╘╬╬╬╬╬╬╬ ╠╬╬╬╬╬╬╬ ╙╬╬╬╬╬╬╬╬
//

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;

import "../interface/IERC20.sol";
import "../lib/SafeERC20.sol";
import "../YakAdapter.sol";

interface IFactory {
function getPair(address,address,bool) external view returns (address);
}

interface IPair {
function getAmountOut(uint256, address) external view returns (uint256);
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external;
}

contract VelocoreAdapter is YakAdapter {
using SafeERC20 for IERC20;

address immutable FACTORY;

constructor(
string memory _name,
address _factory,
uint256 _swapGasEstimate
) YakAdapter(_name, _swapGasEstimate) {
FACTORY = _factory;
}

function getQuoteAndPair(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) internal view returns (uint256 amountOut, address pair) {
address stablePair = IFactory(FACTORY).getPair(_tokenIn, _tokenOut, true);
uint amountOutStable;
if (stablePair > address(0))
amountOutStable = IPair(stablePair).getAmountOut(_amountIn, _tokenIn);

pair = IFactory(FACTORY).getPair(_tokenIn, _tokenOut, false);
if (pair > address(0))
amountOut = IPair(pair).getAmountOut(_amountIn, _tokenIn);

if (amountOutStable > amountOut) {
amountOut = amountOutStable;
pair = stablePair;
}
}

function _query(
uint256 _amountIn,
address _tokenIn,
address _tokenOut
) internal view override returns (uint256 amountOut) {
if (_tokenIn != _tokenOut && _amountIn != 0)
(amountOut, ) = getQuoteAndPair(_amountIn, _tokenIn, _tokenOut);
}

function _swap(
uint256 _amountIn,
uint256 _amountOut,
address _tokenIn,
address _tokenOut,
address to
) internal override {
(uint256 amountOut, address pair) = getQuoteAndPair(_amountIn, _tokenIn, _tokenOut);
require(amountOut >= _amountOut, "Insufficent amount out");
(uint256 amount0Out, uint256 amount1Out) = (_tokenIn < _tokenOut)
? (uint256(0), amountOut)
: (amountOut, uint256(0));
IERC20(_tokenIn).safeTransfer(pair, _amountIn);
IPair(pair).swap(amount0Out, amount1Out, to, new bytes(0));
}
}
Loading