Skip to content

Commit fd58b31

Browse files
committed
add new chains
1 parent 15d6878 commit fd58b31

12 files changed

+463
-45
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright (C) 2020 Zerion Inc. <https://zerion.io>
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
//
16+
// SPDX-License-Identifier: LGPL-3.0-only
17+
18+
pragma solidity 0.8.12;
19+
20+
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
21+
22+
import { ICaller } from "../interfaces/ICaller.sol";
23+
import { IPermit2 } from "../interfaces/IPermit2.sol";
24+
import { Base } from "../shared/Base.sol";
25+
import { ZeroTarget } from "../shared/Errors.sol";
26+
import { Permit2 } from "../shared/Permit2.sol";
27+
import { TokensHandler } from "../shared/TokensHandler.sol";
28+
29+
/**
30+
* @title Simple caller that passes through any call and forwards return tokens
31+
* @dev It also works in fixed outputs case, when input token overhead is refunded
32+
* @dev This contracts uses Permit2 contract in case of Uniswap's Universal Router usage
33+
*/
34+
contract SimpleCallerWithPermit2 is ICaller, TokensHandler, Permit2 {
35+
address internal constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
36+
37+
/**
38+
* @notice Sets Permit2 address for the current chain
39+
* @param permit2 Wrapped Ether address
40+
*/
41+
constructor(address universalRouter, address permit2) Permit2(universalRouter, permit2) {
42+
// solhint-disable-previous-line no-empty-blocks
43+
}
44+
45+
/**
46+
* @notice Main external function: decodes `callerCallData` bytes,
47+
* executes external call, and returns tokens back to `msg.sender` (i.e. Router contract)
48+
* @param callerCallData ABI-encoded parameters:
49+
* - inputToken Address of the token that should be approved to the allowance target
50+
* - allowanceTarget Address to approve `inputToken` to
51+
* - callTarget Address to forward the external call to
52+
* - callData Call data to be used in the external call
53+
* - outputToken Address of the token that should be returned
54+
* @dev Call target cannot be zero
55+
*/
56+
function callBytes(bytes calldata callerCallData) external override {
57+
(
58+
address inputToken,
59+
address allowanceTarget,
60+
address payable callTarget,
61+
bytes memory callData,
62+
address outputToken
63+
) = abi.decode(callerCallData, (address, address, address, bytes, address));
64+
if (callTarget == address(0)) revert ZeroTarget();
65+
66+
// Approve tokens to the allowance target, call the call target
67+
approveAndCall(inputToken, allowanceTarget, callTarget, callData);
68+
69+
// In case of non-zero input token, transfer the remaining amount back to `msg.sender`
70+
Base.transfer(inputToken, msg.sender, Base.getBalance(inputToken));
71+
72+
// In case of non-zero output token, transfer the total balance to `msg.sender`
73+
Base.transfer(outputToken, msg.sender, Base.getBalance(outputToken));
74+
}
75+
76+
/**
77+
* @dev Approves input tokens (if necessary) and calls the target with the provided call data
78+
* @dev Approval and allowance check for `address(0)` token address are skipped
79+
* @param inputToken Address of the token that should be approved to the allowance target
80+
* @param allowanceTarget Address to approve `inputToken` to
81+
* @param callTarget Address to forward the external call to
82+
* @param callData Call data for the call to the target
83+
*/
84+
function approveAndCall(
85+
address inputToken,
86+
address allowanceTarget,
87+
address callTarget,
88+
bytes memory callData
89+
) internal {
90+
uint256 amount = Base.getBalance(inputToken);
91+
if (inputToken == ETH) {
92+
Address.functionCallWithValue(
93+
callTarget,
94+
callData,
95+
amount,
96+
"SC: payable call failed w/ no reason"
97+
);
98+
return;
99+
}
100+
101+
if (inputToken != address(0) && allowanceTarget != address(0)) {
102+
address permit2 = getPermit2();
103+
104+
if (allowanceTarget == getUniversalRouter()) {
105+
Base.safeApproveMax(inputToken, permit2, amount);
106+
IPermit2(permit2).approve(
107+
inputToken,
108+
allowanceTarget,
109+
type(uint160).max,
110+
type(uint48).max
111+
);
112+
} else {
113+
Base.safeApproveMax(inputToken, allowanceTarget, amount);
114+
}
115+
}
116+
117+
Address.functionCall(callTarget, callData, "SC: call failed w/ no reason");
118+
}
119+
}

contracts/interfaces/IPermit2.sol

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (C) 2020 Zerion Inc. <https://zerion.io>
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
//
16+
// SPDX-License-Identifier: LGPL-3.0-only
17+
18+
pragma solidity 0.8.12;
19+
20+
interface IPermit2 {
21+
/// @notice Approves the spender to use up to amount of the specified token up until the expiration
22+
/// @param token The token to approve
23+
/// @param spender The spender address to approve
24+
/// @param amount The approved amount of the token
25+
/// @param expiration The timestamp at which the approval is no longer valid
26+
/// @dev The packed allowance also holds a nonce, which will stay unchanged in approve
27+
/// @dev Setting amount to type(uint160).max sets an unlimited approval
28+
function approve(address token, address spender, uint160 amount, uint48 expiration) external;
29+
}

contracts/shared/Permit2.sol

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (C) 2020 Zerion Inc. <https://zerion.io>
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU General Public License as published by
5+
// the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
//
16+
// SPDX-License-Identifier: LGPL-3.0-only
17+
18+
pragma solidity 0.8.12;
19+
20+
/**
21+
* @title Abstract contract storing Universal Router & Permit2 addresses for the current chain
22+
*/
23+
abstract contract Permit2 {
24+
address private immutable UNIVERSAL_ROUTER;
25+
address private immutable PERMIT2;
26+
27+
/**
28+
* @notice Sets Wrapped Ether address for the current chain
29+
* @param universalRouter Universal Router address
30+
* @param permit2 Permit2 address
31+
*/
32+
constructor(address universalRouter, address permit2) {
33+
UNIVERSAL_ROUTER = universalRouter;
34+
PERMIT2 = permit2;
35+
}
36+
37+
/**
38+
* @notice Returns Universal Router address for the current chain
39+
* @return universalRouter Universal Router address
40+
*/
41+
function getUniversalRouter() public view returns (address universalRouter) {
42+
return UNIVERSAL_ROUTER;
43+
}
44+
45+
/**
46+
* @notice Returns Permit2 address for the current chain
47+
* @return permit2 Permit2 address
48+
*/
49+
function getPermit2() public view returns (address permit2) {
50+
return PERMIT2;
51+
}
52+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
import { HardhatRuntimeEnvironment } from "hardhat/types";
3+
import deploymentAddresses from "../scripts/deployment";
4+
5+
import dotenv from 'dotenv';
6+
dotenv.config();
7+
8+
import deployContractZkSyncEra from './deployContractZkSyncEra';
9+
10+
export default async function (hre: HardhatRuntimeEnvironment) {
11+
try {
12+
const chainIdHex = await hre.network.provider.request({ method: 'eth_chainId' });
13+
const chainId = parseInt(chainIdHex.toString(), 16);
14+
console.log(`Working with chainId ${chainId}`);
15+
await deployContractZkSyncEra(hre, 'callers/', 'SimpleCallerWithPermit2', [deploymentAddresses.universalRouter[chainId], deploymentAddresses.permit2[chainId]]);
16+
} catch (error) {
17+
console.error(error);
18+
process.exit(1);
19+
}
20+
}

deploy/3_setup_router_fee_zksync_era.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import * as ContractArtifact from "../artifacts-zk/contracts/router/Router.sol/R
1111
export default async function (hre: HardhatRuntimeEnvironment) {
1212
try {
1313
// @ts-ignore
14-
const provider = new Provider(hre.userConfig.networks?.zkSyncEra?.url);
14+
const provider = new Provider(hre.userConfig.networks?.zero?.url);
1515

1616
const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || "";
1717
const signer = new ethers.Wallet(PRIVATE_KEY, provider);
@@ -27,15 +27,16 @@ export default async function (hre: HardhatRuntimeEnvironment) {
2727
);
2828

2929
console.log(`Working with chainId ${chainId}`);
30+
console.log(`RPC URL is ${hre.userConfig.networks?.zero?.url}`);
3031

31-
const feeSignerTx = await router.functions.setProtocolFeeSigner(
32-
'0x1e126951a7CB895543E4E4c7B2D1398b3C3d09fC',
33-
);
34-
console.log(`Setting fee signer tx hash: ${feeSignerTx.hash}`);
32+
// const feeSignerTx = await router.functions.setProtocolFeeSigner(
33+
// '0x1e126951a7CB895543E4E4c7B2D1398b3C3d09fC',
34+
// );
35+
// console.log(`Setting fee signer tx hash: ${feeSignerTx.hash}`);
3536

3637
const feeDefaultTx = await router.functions.setProtocolFeeDefault(
3738
[
38-
'5000000000000000',
39+
'8000000000000000',
3940
deploymentAddresses.feeBeneficiaries[chainId],
4041
],
4142
);
@@ -44,4 +45,4 @@ export default async function (hre: HardhatRuntimeEnvironment) {
4445
console.error(error);
4546
process.exit(1);
4647
}
47-
}
48+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
import { HardhatRuntimeEnvironment } from "hardhat/types";
3+
4+
import dotenv from 'dotenv';
5+
dotenv.config();
6+
7+
import deployContractZkSyncEra from './deployContractZkSyncEra';
8+
import deploymentAddresses from "../scripts/deployment";
9+
10+
export default async function (hre: HardhatRuntimeEnvironment) {
11+
try {
12+
const chainIdHex = await hre.network.provider.request({ method: 'eth_chainId' });
13+
const chainId = parseInt(chainIdHex.toString(), 16);
14+
console.log(`Working with chainId ${chainId}`);
15+
16+
await deployContractZkSyncEra(hre, 'callers/', 'UniswapV2Caller', [deploymentAddresses.weth[chainId]]);
17+
} catch (error) {
18+
console.error(error);
19+
process.exit(1);
20+
}
21+
}

deploy/deployContractZkSyncEra.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Wallet } from "zksync-web3";
22
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";
33

4-
async function deployAsyncZkSyncEra(hre, path, contractName) {
4+
async function deployAsyncZkSyncEra(hre, path, contractName, args) {
55
// // load wallet private key from env file
66
const PRIVATE_KEY = process.env.WALLET_PRIVATE_KEY || "";
77

@@ -12,7 +12,7 @@ async function deployAsyncZkSyncEra(hre, path, contractName) {
1212
const deployer = new Deployer(hre, wallet);
1313
const artifact = await deployer.loadArtifact(contractName);
1414

15-
const contract = await deployer.deploy(artifact);
15+
const contract = await deployer.deploy(artifact, args);
1616

1717
console.log(`${contractName} deployed to: ${contract.address}`);
1818

@@ -23,15 +23,15 @@ async function deployAsyncZkSyncEra(hre, path, contractName) {
2323
await hre.run("verify:verify", {
2424
address: contract.address,
2525
contract: contractFullyQualifedName,
26-
constructorArguments: [],
26+
constructorArguments: args,
2727
bytecode: artifact.bytecode,
2828
});
2929

3030
return contract.address;
3131
}
3232

33-
const deployContractZkSyncEra = (hre, path, contractName) => {
34-
return deployAsyncZkSyncEra(hre, path, contractName);
33+
const deployContractZkSyncEra = (hre, path, contractName, args = []) => {
34+
return deployAsyncZkSyncEra(hre, path, contractName, args);
3535
};
3636

3737
export default deployContractZkSyncEra;

0 commit comments

Comments
 (0)