Skip to content

Commit

Permalink
feat: Gateway methods and Solana deposit (#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
fadeev authored Sep 11, 2024
1 parent 7139675 commit 73b823d
Show file tree
Hide file tree
Showing 53 changed files with 3,522 additions and 543 deletions.
34 changes: 27 additions & 7 deletions contracts/SwapHelperLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ library SwapHelperLib {
if (!existsPairPool) {
return false;
}
uint256[] memory amounts = UniswapV2Library.getAmountsOut(uniswapV2Factory, amountIn, path);
uint256[] memory amounts = UniswapV2Library.getAmountsOut(
uniswapV2Factory,
amountIn,
path
);
return amounts[amounts.length - 1] >= minAmountOut;
}

Expand All @@ -114,7 +118,6 @@ library SwapHelperLib {
address targetZRC20,
uint256 minAmountOut
) internal returns (uint256) {

address[] memory path;
path = new address[](2);
path[0] = zrc20;
Expand All @@ -127,7 +130,8 @@ library SwapHelperLib {
path
);

bool isZETA = targetZRC20 == systemContract.wZetaContractAddress() || zrc20 == systemContract.wZetaContractAddress();
bool isZETA = targetZRC20 == systemContract.wZetaContractAddress() ||
zrc20 == systemContract.wZetaContractAddress();

if (!isSufficientLiquidity && !isZETA) {
path = new address[](3);
Expand Down Expand Up @@ -234,20 +238,36 @@ library SwapHelperLib {
return amounts[0];
}

function getMinOutAmount(SystemContract systemContract, address zrc20, address target, uint256 amountIn) public view returns (uint256 minOutAmount) {
function getMinOutAmount(
SystemContract systemContract,
address zrc20,
address target,
uint256 amountIn
) public view returns (uint256 minOutAmount) {
address[] memory path;

path = new address[](2);
path[0] = zrc20;
path[1] = target;
uint[] memory amounts1 = UniswapV2Library.getAmountsOut(systemContract.uniswapv2FactoryAddress(), amountIn, path);
uint[] memory amounts1 = UniswapV2Library.getAmountsOut(
systemContract.uniswapv2FactoryAddress(),
amountIn,
path
);

path = new address[](3);
path[0] = zrc20;
path[1] = systemContract.wZetaContractAddress();
path[2] = target;
uint[] memory amounts2 = UniswapV2Library.getAmountsOut(systemContract.uniswapv2FactoryAddress(), amountIn, path);
uint[] memory amounts2 = UniswapV2Library.getAmountsOut(
systemContract.uniswapv2FactoryAddress(),
amountIn,
path
);

minOutAmount = amounts1[amounts1.length - 1] > amounts2[amounts2.length - 1] ? amounts1[amounts1.length - 1] : amounts2[amounts2.length - 1];
minOutAmount = amounts1[amounts1.length - 1] >
amounts2[amounts2.length - 1]
? amounts1[amounts1.length - 1]
: amounts2[amounts2.length - 1];
}
}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,12 @@
"typechain-types"
],
"dependencies": {
"@coral-xyz/anchor": "^0.30.1",
"@inquirer/prompts": "^2.1.1",
"@inquirer/select": "1.1.3",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@openzeppelin/contracts": "^4.9.6",
"@solana/web3.js": "^1.95.3",
"@uniswap/v2-periphery": "^1.1.0-beta.0",
"@zetachain/faucet-cli": "^4.1.1",
"@zetachain/networks": "^10.0.0",
Expand Down
1 change: 1 addition & 0 deletions packages/client/src/abi/GatewayEVM.sol/GatewayEVM.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/client/src/abi/GatewayZEVM.sol/GatewayZEVM.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/client/src/abi/ZRC20.sol/ZRC20.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/client/src/abi/ZRC20.sol/ZRC20Errors.json

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions packages/client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import merge from "lodash/merge";

import {
deposit,
evmCall,
evmDeposit,
evmDepositAndCall,
getBalances,
getChainId,
getEndpoint,
Expand All @@ -17,8 +20,12 @@ import {
getZRC20FromERC20,
getZRC20GasToken,
sendZeta,
solanaDeposit,
trackCCTX,
withdraw,
zetachainCall,
zetachainWithdraw,
zetachainWithdrawAndCall,
} from ".";

export interface ZetaChainClientParamsBase {
Expand Down Expand Up @@ -126,4 +133,11 @@ export class ZetaChainClient {
getRefundFee = getRefundFee;
getZRC20FromERC20 = getZRC20FromERC20;
getZRC20GasToken = getZRC20GasToken;
solanaDeposit = solanaDeposit;
zetachainWithdrawAndCall = zetachainWithdrawAndCall;
zetachainWithdraw = zetachainWithdraw;
zetachainCall = zetachainCall;
evmDepositAndCall = evmDepositAndCall;
evmCall = evmCall;
evmDeposit = evmDeposit;
}
48 changes: 48 additions & 0 deletions packages/client/src/evmCall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ethers } from "ethers";

import GatewayABI from "./abi/GatewayEVM.sol/GatewayEVM.json";
import { ZetaChainClient } from "./client";

export const evmCall = async function (
this: ZetaChainClient,
args: {
callOnRevert: boolean;
gasLimit: number;
gasPrice: ethers.BigNumber;
gatewayEvm: string;
onRevertGasLimit: number;
receiver: string;
revertAddress: string;
revertMessage: string;
types: string;
values: any[];
}
) {
const signer = this.signer;
const { utils } = ethers;
const gateway = new ethers.Contract(args.gatewayEvm, GatewayABI.abi, signer);

const encodedParameters = utils.defaultAbiCoder.encode(
JSON.parse(args.types),
args.values
);
const tx = await gateway[
"call(address,bytes,(address,bool,address,bytes,uint256))"
](
args.receiver,
encodedParameters,
{
abortAddress: "0x0000000000000000000000000000000000000000",
callOnRevert: args.callOnRevert,
onRevertGasLimit: args.onRevertGasLimit,
revertAddress: args.revertAddress,
revertMessage: utils.hexlify(utils.toUtf8Bytes(args.revertMessage)),
},
{
gasLimit: args.gasLimit,
gasPrice: args.gasPrice,
}
);

return tx;
};
68 changes: 68 additions & 0 deletions packages/client/src/evmDeposit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import ERC20_ABI from "@openzeppelin/contracts/build/contracts/ERC20.json";
import { ethers } from "ethers";

import GatewayABI from "./abi/GatewayEVM.sol/GatewayEVM.json";
import { ZetaChainClient } from "./client";

export const evmDeposit = async function (
this: ZetaChainClient,
args: {
amount: string;
callOnRevert: boolean;
erc20: string;
gasLimit: number;
gasPrice: ethers.BigNumber;
gatewayEvm: string;
onRevertGasLimit: number;
receiver: string;
revertAddress: string;
revertMessage: string;
}
) {
const signer = this.signer;
const { utils } = ethers;
const gateway = new ethers.Contract(args.gatewayEvm, GatewayABI.abi, signer);

const revertOptions = {
abortAddress: "0x0000000000000000000000000000000000000000",
callOnRevert: args.callOnRevert,
onRevertGasLimit: args.onRevertGasLimit,
revertAddress: args.revertAddress,
// not used
revertMessage: utils.hexlify(utils.toUtf8Bytes(args.revertMessage)),
};

const txOptions = {
gasLimit: args.gasLimit,
gasPrice: args.gasPrice,
};
let tx;
if (args.erc20) {
const erc20Contract = new ethers.Contract(
args.erc20,
ERC20_ABI.abi,
signer
);
const decimals = await erc20Contract.decimals();
const value = utils.parseUnits(args.amount, decimals);
await erc20Contract.connect(signer).approve(args.gatewayEvm, value);
const method =
"deposit(address,uint256,address,(address,bool,address,bytes,uint256))";
tx = await gateway[method](
args.receiver,
value,
args.erc20,
revertOptions,
txOptions
);
} else {
const value = utils.parseEther(args.amount);
const method = "deposit(address,(address,bool,address,bytes,uint256))";
tx = await gateway[method](args.receiver, revertOptions, {
...txOptions,
value,
});
}

return tx;
};
82 changes: 82 additions & 0 deletions packages/client/src/evmDepositAndCall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import ERC20_ABI from "@openzeppelin/contracts/build/contracts/ERC20.json";
import { ethers } from "ethers";

import GatewayABI from "./abi/GatewayEVM.sol/GatewayEVM.json";
import { ZetaChainClient } from "./client";

export const evmDepositAndCall = async function (
this: ZetaChainClient,
args: {
amount: string;
callOnRevert: boolean;
erc20: string;
gasLimit: number;
gasPrice: ethers.BigNumber;
gatewayEvm: string;
onRevertGasLimit: number;
receiver: string;
revertAddress: string;
revertMessage: string;
types: string;
values: any[];
}
) {
const signer = this.signer;
const { utils } = ethers;
const gateway = new ethers.Contract(args.gatewayEvm, GatewayABI.abi, signer);

const revertOptions = {
abortAddress: "0x0000000000000000000000000000000000000000",
callOnRevert: args.callOnRevert,
onRevertGasLimit: args.onRevertGasLimit,
revertAddress: args.revertAddress,
// not used
revertMessage: utils.hexlify(utils.toUtf8Bytes(args.revertMessage)),
};

const txOptions = {
gasLimit: args.gasLimit,
gasPrice: args.gasPrice,
};

const encodedParameters = utils.defaultAbiCoder.encode(
JSON.parse(args.types),
args.values
);
let tx;
if (args.erc20) {
const erc20Contract = new ethers.Contract(
args.erc20,
ERC20_ABI.abi,
signer
);
const decimals = await erc20Contract.decimals();
const value = utils.parseUnits(args.amount, decimals);
await erc20Contract.connect(signer).approve(args.gatewayEvm, value);
const method =
"depositAndCall(address,uint256,address,bytes,(address,bool,address,bytes,uint256))";
tx = await gateway[method](
args.receiver,
value,
args.erc20,
encodedParameters,
revertOptions,
txOptions
);
} else {
const value = utils.parseEther(args.amount);
const method =
"depositAndCall(address,bytes,(address,bool,address,bytes,uint256))";
tx = await gateway[method](
args.receiver,
encodedParameters,
revertOptions,
{
...txOptions,
value,
}
);
}

return tx;
};
Loading

0 comments on commit 73b823d

Please sign in to comment.