-
Notifications
You must be signed in to change notification settings - Fork 5
Description
Problem description
I tried to interact with the contract through JavaScript, but during the interaction, I was affected by the getAmountsOut contract interface, which resulted in an indirect loss of over $500 in my two interactions. I hope that the official can provide a response.
POC
Here is the code poc.js
import { ethers } from 'ethers';
import { Wallet, Provider } from "zksync-web3";
// Please replace with your infura provider API key
const infuraProviderApiKey = "c0************************662";
// Please replace with your wallet private key
const privateKey = "e**********************************************a"
const wEthAddress = "0x5aea5775959fbc2557cc8789bc1bf90a239d9a91";
const usdcAddress = "0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4";
const muteSwitchRouterAddress = "0x8B791913eB07C32779a16750e3868aA8495F5964";
// For a more comprehensive ABI, please refer to https://wiki.mute.io/mute/mute-switch-api/abis
const routerABI = [
{
"inputs": [{
"internalType": "uint256",
"name": "amountIn",
"type": "uint256"
}, {
"internalType": "address[]",
"name": "path",
"type": "address[]"
}, {
"internalType": "bool[]",
"name": "stable",
"type": "bool[]"
}],
"name": "getAmountsOut",
"outputs": [{
"internalType": "uint256[]",
"name": "amounts",
"type": "uint256[]"
}],
"stateMutability": "view",
"type": "function"
}
]
async function getAmountsOut(wallet, _tokenIn, _tokenOut, _amountIn, _stable) {
const router = new ethers.Contract(muteSwitchRouterAddress, routerABI, wallet);
const amountIn = _tokenIn === wEthAddress ? ethers.utils.parseEther(_amountIn) : ethers.utils.parseUnits(_amountIn, 6);
const path = [_tokenIn, _tokenOut];
const amountOutRes = await router.getAmountsOut(amountIn, path, _stable);
// console.log(amountOutRes);
const amountOutMin = amountOutRes[1];
const amountOut = _tokenOut === wEthAddress ? ethers.utils.formatEther(amountOutMin) : ethers.utils.formatUnits(amountOutMin, 6);
console.log(`Swap ${_amountIn} ${_tokenIn === wEthAddress ? 'ETH' : 'USDC'} to ${_tokenOut === wEthAddress ? 'ETH' : 'USDC'} you will received: ${amountOut} by using parameters [${_stable}]`);
return amountOutMin;
}
async function compare() {
const ethersProvider = new ethers.providers.InfuraProvider("homestead", infuraProviderApiKey);
const zkSyncProvider = new Provider("https://mainnet.era.zksync.io");
const wallet = new Wallet(privateKey, zkSyncProvider, ethersProvider);
var stable = [true, false];
await getAmountsOut(wallet, wEthAddress, usdcAddress, "0.5", stable);
stable = [false, true];
await getAmountsOut(wallet, wEthAddress, usdcAddress, "0.5", stable);
}
await compare();
package.json
"dependencies": {
"ethers": "^5.7.2",
"zksync-web3": "^0.16.0"
}
Run Step
npm install
node poc.js
Result
Swap 0.5 ETH to USDC you will received: 832.881692 by using parameters [true,false]
Swap 0.5 ETH to USDC you will received: 1123.559205 by using parameters [false,true]
Conclusion
As you can see, the stable parameter is very confusing, and both parameters can complete the interaction normally, but the amount difference is very significant, which leads to a direct loss of over $500 for my following interaction.
https://explorer.zksync.io/tx/0xd9b3975447a9864c168317f62fb32559d066d9f89fd08db79ba300153b82e5b8
https://explorer.zksync.io/tx/0xe4edcccd8123e65e499ccbb9adb0ffcceb8227cbaff8ecefd44e3daf6349ec2c
I am looking forward to the official reply. Is this a contract specific mechanism or should it be considered a contract defect.