-
Notifications
You must be signed in to change notification settings - Fork 0
/
FeedThePrize.sol
177 lines (142 loc) · 6.08 KB
/
FeedThePrize.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
import "./SafeMath.sol";
import "./Ownable.sol";
abstract contract IdleDAIV3 {
function mintIdleToken(uint256 _amount, bool _skipWholeRebalance) virtual public returns(uint256);
function reedemIdleToken(uint256 _amount, bool _skipRebalance, uint256[] calldata _clientProtocolAmounts) virtual external returns(uint256);
function balanceOf(address account) virtual public returns(uint256);
function tokenPrice() virtual public returns(uint256);
function tokenDecimals() virtual public returns(uint256);
}
abstract contract PoolTogetherDAI {
function depositSponsorship(uint256 _amount) virtual public;
function withdrawSponsorshipAndFee(uint256 _amount) virtual public;
function balanceOf(address _addr) virtual public returns(uint256);
}
/**
* @title FeedThePrize
* @dev Feed the PoolTogether prize
*/
contract FeedThePrize is Ownable{
using SafeMath for uint256;
// amount stored in DAI
mapping(address => uint256) public feedBook;
uint256 public idleTotalA = 0;
uint256 public ptTotalA = 0;
event FeedPrize(address indexed _from, uint256 _amount);
event FeedPT(address indexed _from, uint256 _amount);
event FeedIdle(address indexed _from, uint256 _amount);
event Withdraw(address indexed _from, uint256 _amount);
event WithdrawPT(address indexed _from, uint256 _amount);
event WithdrawIdle(address indexed _from, uint256 _amount);
constructor() public {
}
IdleDAIV3 public idleP = IdleDAIV3(0x78751B12Da02728F467A44eAc40F5cbc16Bd7934);
PoolTogetherDAI public ptP = PoolTogetherDAI(0x29fe7D60DdF151E5b52e5FAB4f1325da6b2bD958);
// Feed Pool functions
function feedPrize(uint256 _amount) public payable {
require(_amount > 0, "The amount to feed has to be greater than 0");
uint256 amountToFeed = _amount;
uint256 idleA = 0;
uint256 ptA = 0;
(ptA, idleA) = getExceedAndRebalanceAmount(amountToFeed, true);
if(idleA > 0) {
idleP.mintIdleToken(idleA, true);
feedBook[msg.sender] = feedBook[msg.sender].add(idleA);
idleTotalA = idleTotalA.add(idleA);
emit FeedIdle(msg.sender, idleA);
}
if(ptA > 0) {
ptP.depositSponsorship(ptA);
feedBook[msg.sender] = feedBook[msg.sender].add(ptA);
ptTotalA = ptTotalA.add(ptA);
emit FeedPT(msg.sender, ptA);
}
emit FeedPrize(msg.sender, amountToFeed);
}
function withdraw(uint256 _amount) public {
require(_amount > 0, "The amount to withdraw has to be greater than 0");
uint256 amountToW = _amount;
require(amountToW <= feedBook[msg.sender], "Funds not sufficient for this address");
uint256 idleW = 0;
uint256 ptW = 0;
(ptW, idleW) = getExceedAndRebalanceAmount(amountToW, false);
if (idleW > 0) {
uint256[] memory empty;
uint256 idleTokenAmount = idleW.div(idleP.tokenPrice());
idleP.reedemIdleToken(idleTokenAmount, true, empty);
feedBook[msg.sender] = feedBook[msg.sender].sub(idleW);
idleTotalA = idleTotalA.sub(idleW);
emit WithdrawIdle(msg.sender, idleW);
}
if (ptW > 0) {
ptP.withdrawSponsorshipAndFee(ptW);
feedBook[msg.sender] = feedBook[msg.sender].sub(ptW);
ptTotalA = ptTotalA.sub(ptW);
emit WithdrawPT(msg.sender, ptW);
}
emit Withdraw(msg.sender, amountToW);
}
function getExceedAndRebalanceAmount(uint256 amount, bool feed) public returns(uint256, uint256) {
uint256 ptAmount = 0;
uint256 idleAmount = 0;
uint256 amountToSplit = 0;
uint256 amountToRebalance = 0;
uint256 idleBalance = getIdleBalance();
if(feed) {
if (idleBalance > ptTotalA) {
amountToRebalance = idleBalance.sub(ptTotalA);
if (amountToRebalance >= amount) {
ptAmount = amount;
} else {
ptAmount = amountToRebalance;
}
} else if(idleBalance < ptTotalA) {
amountToRebalance = ptTotalA.sub(idleBalance);
if (amountToRebalance >= amount) {
idleAmount = amount;
} else {
idleAmount = amountToRebalance;
}
}
} else {
if (idleBalance > ptTotalA) {
amountToRebalance = idleBalance.sub(ptTotalA);
if (amountToRebalance >= amount) {
idleAmount = amount;
} else {
idleAmount = amountToRebalance;
}
} else if(idleBalance < ptTotalA) {
amountToRebalance = ptTotalA.sub(idleBalance);
if (amountToRebalance >= amount) {
ptAmount = amount;
} else {
ptAmount = amountToRebalance;
}
}
}
if(ptAmount != amount && idleAmount != amount) {
amountToSplit = amount.sub(amountToRebalance);
uint256 amountSplitted = amountToSplit.div(2);
idleAmount = idleAmount.add(amountSplitted);
ptAmount = ptAmount.add(amountSplitted);
}
require(idleAmount.add(ptAmount) == amount, "The total amount has to be the same");
return (ptAmount, idleAmount);
}
// Return balance in DAI
function getIdleBalance() public returns(uint256) {
return idleP.balanceOf(address(this)).mul(idleP.tokenPrice());
}
function getPTBalance() public returns(uint256) {
return ptP.balanceOf(address(this));
}
function getTotalA() public view returns(uint256) {
return idleTotalA.add(ptTotalA);
}
function getInterestEarned() public returns(uint256) {
return getIdleBalance().sub(idleTotalA);
}
}