-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPuppetV3Pool.sol
71 lines (57 loc) · 2.64 KB
/
PuppetV3Pool.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// SPDX-License-Identifier: MIT
pragma solidity =0.7.6;
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)));
}
}