Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contracts/IRewardDistributionRecipient.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import "@openzeppelin/contracts/ownership/Ownable.sol";


contract IRewardDistributionRecipient is Ownable {
address rewardDistribution;
address public rewardDistribution;

function notifyRewardAmount(uint256 reward) external;

Expand Down
134 changes: 134 additions & 0 deletions contracts/iETHRewards.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
pragma solidity ^0.5.0;

import "@openzeppelin/contracts/math/Math.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";
import "@openzeppelin/contracts/ownership/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./IRewardDistributionRecipient.sol";

contract LPTokenWrapper {
using SafeMath for uint256;
using SafeERC20 for IERC20;

IERC20 public token = IERC20(0xA9859874e1743A32409f75bB11549892138BBA1E);

uint256 private _totalSupply;
mapping(address => uint256) private _balances;

function totalSupply() public view returns (uint256) {
return _totalSupply;
}

function balanceOf(address account) public view returns (uint256) {
return _balances[account];
}

function stake(uint256 amount) public {
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
token.safeTransferFrom(msg.sender, address(this), amount);
}

function withdraw(uint256 amount) public {
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
token.safeTransfer(msg.sender, amount);
}
}

contract iETHRewards is LPTokenWrapper, IRewardDistributionRecipient {
IERC20 public snx = IERC20(0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F);
uint256 public constant DURATION = 7 days;

uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;

event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);

modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}

function lastTimeRewardApplicable() public view returns (uint256) {
return Math.min(block.timestamp, periodFinish);
}

function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}

function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}

// stake visibility is public as overriding LPTokenWrapper's stake() function
function stake(uint256 amount) public updateReward(msg.sender) {
require(amount > 0, "Cannot stake 0");
super.stake(amount);
emit Staked(msg.sender, amount);
}

function withdraw(uint256 amount) public updateReward(msg.sender) {
require(amount > 0, "Cannot withdraw 0");
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
}

function exit() external {
withdraw(balanceOf(msg.sender));
getReward();
}

function getReward() public updateReward(msg.sender) {
uint256 reward = earned(msg.sender);
if (reward > 0) {
rewards[msg.sender] = 0;
snx.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}

function notifyRewardAmount(uint256 reward)
external
onlyRewardDistribution
updateReward(address(0))
{
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(DURATION);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
rewardRate = reward.add(leftover).div(DURATION);
}
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(DURATION);
emit RewardAdded(reward);
}
}
1 change: 1 addition & 0 deletions deployments/iETHRewards.full.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"}],"name":"RewardPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"constant":true,"inputs":[],"name":"DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"exit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"getReward","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastUpdateTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"reward","type":"uint256"}],"name":"notifyRewardAmount","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"periodFinish","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"rewardDistribution","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_rewardDistribution","type":"address"}],"name":"setRewardDistribution","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"snx","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
1 change: 1 addition & 0 deletions deployments/iETHRewards.full.bin
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6080604052600080546001600160a01b031990811673a9859874e1743a32409f75bb11549892138bba1e1782556005805490911673c011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f17905560068190556007556100646001600160e01b036100b516565b600380546001600160a01b0319166001600160a01b0392831617908190556040519116906000907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36100b9565b3390565b611209806100c86000396000f3fe608060405234801561001057600080fd5b50600436106101725760003560e01c806380faa57d116100de578063cd3daf9d11610097578063e9fad8ee11610071578063e9fad8ee14610338578063ebe2b12b14610340578063f2fde38b14610348578063fc0c546a1461036e57610172565b8063cd3daf9d14610320578063df136d6514610328578063e7d279981461033057610172565b806380faa57d146102a95780638b876347146102b15780638da5cb5b146102d75780638f32d59b146102df578063a694fc3a146102fb578063c8f33c911461031857610172565b80632e1a7d4d116101305780632e1a7d4d146102315780633c6b16ab1461024e5780633d18b9121461026b57806370a0823114610273578063715018a6146102995780637b0a47ee146102a157610172565b80628cc262146101775780630700037d146101af5780630d68b761146101d5578063101114cf146101fd57806318160ddd146102215780631be0528914610229575b600080fd5b61019d6004803603602081101561018d57600080fd5b50356001600160a01b0316610376565b60408051918252519081900360200190f35b61019d600480360360208110156101c557600080fd5b50356001600160a01b03166103fc565b6101fb600480360360208110156101eb57600080fd5b50356001600160a01b031661040e565b005b610205610489565b604080516001600160a01b039092168252519081900360200190f35b61019d610498565b61019d61049f565b6101fb6004803603602081101561024757600080fd5b50356104a6565b6101fb6004803603602081101561026457600080fd5b503561058d565b6101fb610707565b61019d6004803603602081101561028957600080fd5b50356001600160a01b03166107d9565b6101fb6107f4565b61019d610897565b61019d61089d565b61019d600480360360208110156102c757600080fd5b50356001600160a01b03166108b0565b6102056108c2565b6102e76108d1565b604080519115158252519081900360200190f35b6101fb6004803603602081101561031157600080fd5b50356108f7565b61019d6109db565b61019d6109e1565b61019d610a35565b610205610a3b565b6101fb610a4a565b61019d610a65565b6101fb6004803603602081101561035e57600080fd5b50356001600160a01b0316610a6b565b610205610ad0565b6001600160a01b0381166000908152600b6020908152604080832054600a9092528220546103f691906103ea90670de0b6b3a7640000906103de906103c9906103bd6109e1565b9063ffffffff610adf16565b6103d2886107d9565b9063ffffffff610b2816565b9063ffffffff610b8116565b9063ffffffff610bc316565b92915050565b600b6020526000908152604090205481565b6104166108d1565b610467576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600480546001600160a01b0319166001600160a01b0392909216919091179055565b6004546001600160a01b031681565b6001545b90565b62093a8081565b336104af6109e1565b6009556104ba61089d565b6008556001600160a01b03811615610501576104d581610376565b6001600160a01b0382166000908152600b6020908152604080832093909355600954600a909152919020555b6000821161054a576040805162461bcd60e51b8152602060048201526011602482015270043616e6e6f74207769746864726177203607c1b604482015290519081900360640190fd5b61055382610c1d565b60408051838152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a25050565b6004546001600160a01b03166105a1610c7e565b6001600160a01b0316146105e65760405162461bcd60e51b815260040180806020018281038252602181526020018061118a6021913960400191505060405180910390fd5b60006105f06109e1565b6009556105fb61089d565b6008556001600160a01b038116156106425761061681610376565b6001600160a01b0382166000908152600b6020908152604080832093909355600954600a909152919020555b60065442106106665761065e8262093a8063ffffffff610b8116565b6007556106b4565b60065460009061067c904263ffffffff610adf16565b9050600061069560075483610b2890919063ffffffff16565b90506106ae62093a806103de868463ffffffff610bc316565b60075550505b4260088190556106cd9062093a8063ffffffff610bc316565b6006556040805183815290517fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9181900360200190a15050565b336107106109e1565b60095561071b61089d565b6008556001600160a01b038116156107625761073681610376565b6001600160a01b0382166000908152600b6020908152604080832093909355600954600a909152919020555b600061076d33610376565b905080156107d557336000818152600b602052604081205560055461079e916001600160a01b039091169083610c82565b60408051828152905133917fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e0486919081900360200190a25b5050565b6001600160a01b031660009081526002602052604090205490565b6107fc6108d1565b61084d576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6003546040516000916001600160a01b0316907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600380546001600160a01b0319169055565b60075481565b60006108ab42600654610cd9565b905090565b600a6020526000908152604090205481565b6003546001600160a01b031690565b6003546000906001600160a01b03166108e8610c7e565b6001600160a01b031614905090565b336109006109e1565b60095561090b61089d565b6008556001600160a01b038116156109525761092681610376565b6001600160a01b0382166000908152600b6020908152604080832093909355600954600a909152919020555b60008211610998576040805162461bcd60e51b815260206004820152600e60248201526d043616e6e6f74207374616b6520360941b604482015290519081900360640190fd5b6109a182610cef565b60408051838152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a25050565b60085481565b60006109eb610498565b6109f8575060095461049c565b6108ab610a26610a06610498565b6103de670de0b6b3a76400006103d26007546103d26008546103bd61089d565b6009549063ffffffff610bc316565b60095481565b6005546001600160a01b031681565b610a5b610a56336107d9565b6104a6565b610a63610707565b565b60065481565b610a736108d1565b610ac4576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610acd81610d51565b50565b6000546001600160a01b031681565b6000610b2183836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250610df2565b9392505050565b600082610b37575060006103f6565b82820282848281610b4457fe5b0414610b215760405162461bcd60e51b81526004018080602001828103825260218152602001806111696021913960400191505060405180910390fd5b6000610b2183836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250610e89565b600082820183811015610b21576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600154610c30908263ffffffff610adf16565b60015533600090815260026020526040902054610c53908263ffffffff610adf16565b336000818152600260205260408120929092559054610acd916001600160a01b039091169083610c82565b3390565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610cd4908490610eee565b505050565b6000818310610ce85781610b21565b5090919050565b600154610d02908263ffffffff610bc316565b60015533600090815260026020526040902054610d25908263ffffffff610bc316565b336000818152600260205260408120929092559054610acd916001600160a01b039091169030846110ac565b6001600160a01b038116610d965760405162461bcd60e51b81526004018080602001828103825260268152602001806111436026913960400191505060405180910390fd5b6003546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600380546001600160a01b0319166001600160a01b0392909216919091179055565b60008184841115610e815760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015610e46578181015183820152602001610e2e565b50505050905090810190601f168015610e735780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60008183610ed85760405162461bcd60e51b8152602060048201818152835160248401528351909283926044909101919085019080838360008315610e46578181015183820152602001610e2e565b506000838581610ee457fe5b0495945050505050565b610f00826001600160a01b0316611106565b610f51576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310610f8f5780518252601f199092019160209182019101610f70565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610ff1576040519150601f19603f3d011682016040523d82523d6000602084013e610ff6565b606091505b50915091508161104d576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156110a65780806020019051602081101561106957600080fd5b50516110a65760405162461bcd60e51b815260040180806020018281038252602a8152602001806111ab602a913960400191505060405180910390fd5b50505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526110a6908590610eee565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470811580159061113a5750808214155b94935050505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f7743616c6c6572206973206e6f742072657761726420646973747269627574696f6e5361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a72315820b0423be87701a1f17c9e50b0a8152279c7d3bb5c2c0aa4c70f8e28ccb2199ed364736f6c634300050c0032
Loading