generated from ZeframLou/foundry-template
-
Notifications
You must be signed in to change notification settings - Fork 2
/
CurveV2xPYT.sol
106 lines (88 loc) · 3.29 KB
/
CurveV2xPYT.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.4;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {FullMath} from "timeless/lib/FullMath.sol";
import {xPYT} from "../xPYT.sol";
import {ICurveCryptoSwap2ETH} from "./external/ICurveCryptoSwap2ETH.sol";
/// @title CurveV2xPYT
/// @author zefram.eth
/// @notice xPYT implementation using Curve V2 to swap NYT into PYT
/// @dev Assumes for all Curve pools used, coins[0] is NYT and coins[1] is xPYT.
contract CurveV2xPYT is xPYT {
/// -----------------------------------------------------------------------
/// Library usage
/// -----------------------------------------------------------------------
using SafeTransferLib for ERC20;
/// -----------------------------------------------------------------------
/// Errors
/// -----------------------------------------------------------------------
error CurveV2xPYT__AlreadyInitialized();
/// -----------------------------------------------------------------------
/// Storage variables
/// -----------------------------------------------------------------------
/// @notice The Curve V2 pool to swap with
ICurveCryptoSwap2ETH public curvePool;
/// -----------------------------------------------------------------------
/// Constructor
/// -----------------------------------------------------------------------
constructor(
ERC20 asset_,
string memory name_,
string memory symbol_,
uint256 pounderRewardMultiplier_,
uint256 minOutputMultiplier_
)
xPYT(
asset_,
name_,
symbol_,
pounderRewardMultiplier_,
minOutputMultiplier_
)
{}
function initialize(ICurveCryptoSwap2ETH curvePool_) external {
// can't initialize twice
if (address(curvePool) != address(0)) {
revert CurveV2xPYT__AlreadyInitialized();
}
curvePool = curvePool_;
// initialize allowance slot to make future swaps cheaper
nyt.approve(address(curvePool_), 1);
}
/// -----------------------------------------------------------------------
/// Internal utilities
/// -----------------------------------------------------------------------
/// @inheritdoc xPYT
function _getTwapQuote(uint256 nytAmountIn)
internal
view
virtual
override
returns (bool success, uint256 xPytAmountOut)
{
uint256 xPytPriceInNyt = curvePool.price_oracle(); // price of xPYT in NYT, scaled by ONE. Unit is NYT/xPYT
xPytAmountOut = FullMath.mulDiv(nytAmountIn, ONE, xPytPriceInNyt);
success = true;
}
/// @inheritdoc xPYT
function _swap(uint256 nytAmountIn)
internal
virtual
override
returns (uint256 xPytAmountOut)
{
ICurveCryptoSwap2ETH curvePool_ = curvePool;
nyt.approve(address(curvePool_), nytAmountIn + 1);
return curvePool_.exchange(0, 1, nytAmountIn, 0, false, address(this));
}
/// @inheritdoc xPYT
function _quote(uint256 nytAmountIn)
internal
virtual
override
returns (uint256 xPytAmountOut)
{
return curvePool.get_dy(0, 1, nytAmountIn);
}
}