Skip to content

Commit

Permalink
RocketJoeStakingContract and RocketJoeToken
Browse files Browse the repository at this point in the history
  • Loading branch information
LouisMeMyself committed Dec 28, 2021
1 parent b509dbd commit 06f2397
Show file tree
Hide file tree
Showing 29 changed files with 1,766 additions and 17,202 deletions.
207 changes: 207 additions & 0 deletions .openzeppelin/unknown-31337.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
{
"manifestVersion": "3.2",
"admin": {
"address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"txHash": "0x3925b8879e79569cf432ca46b1d26510843db17575488fde9738cc1e0652a5ca",
"deployTransaction": {
"hash": "0x3925b8879e79569cf432ca46b1d26510843db17575488fde9738cc1e0652a5ca",
"blockHash": "0xe59a350229ccf67ec990b3fc5f40b19cd6501a51e0a4bffadaba940a9b497d95",
"blockNumber": 8,
"transactionIndex": 0,
"confirmations": 1,
"from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
"gasPrice": {
"type": "BigNumber",
"hex": "0x511cdedf"
},
"gasLimit": {
"type": "BigNumber",
"hex": "0x0762b4"
},
"to": null,
"value": {
"type": "BigNumber",
"hex": "0x00"
},
"nonce": 7,
"data": "0x608060405234801561001057600080fd5b50600080546001600160a01b031916339081178255604051909182917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350610759806100616000396000f3fe60806040526004361061007b5760003560e01c80639623609d1161004e5780639623609d1461011157806399a88ec414610124578063f2fde38b14610144578063f3b7dead146101645761007b565b8063204e1c7a14610080578063715018a6146100bc5780637eff275e146100d35780638da5cb5b146100f3575b600080fd5b34801561008c57600080fd5b506100a061009b366004610515565b610184565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c857600080fd5b506100d1610215565b005b3480156100df57600080fd5b506100d16100ee366004610554565b610292565b3480156100ff57600080fd5b506000546001600160a01b03166100a0565b6100d161011f36600461058c565b61031c565b34801561013057600080fd5b506100d161013f366004610554565b6103ad565b34801561015057600080fd5b506100d161015f366004610515565b610405565b34801561017057600080fd5b506100a061017f366004610515565b6104ef565b6000806000836001600160a01b03166040516101aa90635c60da1b60e01b815260040190565b600060405180830381855afa9150503d80600081146101e5576040519150601f19603f3d011682016040523d82523d6000602084013e6101ea565b606091505b5091509150816101f957600080fd5b8080602001905181019061020d9190610538565b949350505050565b6000546001600160a01b031633146102485760405162461bcd60e51b815260040161023f906106c0565b60405180910390fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b6000546001600160a01b031633146102bc5760405162461bcd60e51b815260040161023f906106c0565b6040516308f2839760e41b81526001600160a01b038281166004830152831690638f283970906024015b600060405180830381600087803b15801561030057600080fd5b505af1158015610314573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146103465760405162461bcd60e51b815260040161023f906106c0565b60405163278f794360e11b81526001600160a01b03841690634f1ef286903490610376908690869060040161065d565b6000604051808303818588803b15801561038f57600080fd5b505af11580156103a3573d6000803e3d6000fd5b5050505050505050565b6000546001600160a01b031633146103d75760405162461bcd60e51b815260040161023f906106c0565b604051631b2ce7f360e11b81526001600160a01b038281166004830152831690633659cfe6906024016102e6565b6000546001600160a01b0316331461042f5760405162461bcd60e51b815260040161023f906106c0565b6001600160a01b0381166104945760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b606482015260840161023f565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000806000836001600160a01b03166040516101aa906303e1469160e61b815260040190565b600060208284031215610526578081fd5b81356105318161070b565b9392505050565b600060208284031215610549578081fd5b81516105318161070b565b60008060408385031215610566578081fd5b82356105718161070b565b915060208301356105818161070b565b809150509250929050565b6000806000606084860312156105a0578081fd5b83356105ab8161070b565b925060208401356105bb8161070b565b9150604084013567ffffffffffffffff808211156105d7578283fd5b818601915086601f8301126105ea578283fd5b8135818111156105fc576105fc6106f5565b604051601f8201601f19908116603f01168101908382118183101715610624576106246106f5565b8160405282815289602084870101111561063c578586fd5b82602086016020830137856020848301015280955050505050509250925092565b600060018060a01b038416825260206040818401528351806040850152825b818110156106985785810183015185820160600152820161067c565b818111156106a95783606083870101525b50601f01601f191692909201606001949350505050565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461072057600080fd5b5056fea2646970667358221220d849f96f3086b9f82cdcf665adb8c697ace05638da1c7c16ab2d26293717af6764736f6c63430008020033",
"r": "0x8dc260c691908e0f595a908cb61020fc5d2d63951f1f25363717b3a22c96f0c5",
"s": "0x76425f8edf2504f163eb90fa987cdd09ca2fbe5a74c5b1402cac364f3abd8a00",
"v": 1,
"creates": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"chainId": 31337
}
},
"proxies": [
{
"address": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"txHash": "0xcca4a6b44dfe11eacb4a5a0cfcbd3f60bdf09e192cd1041f9c95c223c0e0f382",
"kind": "transparent"
},
{
"address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"txHash": "0xc207da1ba667358fa2e6f0f3a2a1ce11e0b54f9c8ffba0a5231244cd1f8bb1e1",
"kind": "transparent"
},
{
"address": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"txHash": "0x859637882dac1c7388ad4df3082ecc5a7e6c8166e1e3d1312d4e00b89193a4a9",
"kind": "transparent"
},
{
"address": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690",
"txHash": "0x096365e5b2926cbbd9987d6959f86bc375be328df527602772cc42049f60a0b9",
"kind": "transparent"
},
{
"address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"txHash": "0x6d44036c30e369c8b1e181c7cba50f8ccdd6d9e345aafe9716ab9f8dd869a3de",
"kind": "transparent"
},
{
"address": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6",
"txHash": "0x03b7606dcfef6bc0c9b9ce56e020e20703a46e77c3eda53116fed04eaf02d1b1",
"kind": "transparent"
},
{
"address": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1",
"txHash": "0x320b39bd1d445af2ba123874ed3d9e42b47571f05f8c2e398ec400b79b9c9ed6",
"kind": "transparent"
},
{
"address": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
"txHash": "0x7ef92d6e2ab84a9bf83474e7ad33a71ef67679a06205925540beb2bf3240f258",
"kind": "transparent"
},
{
"address": "0x84eA74d481Ee0A5332c457a4d796187F6Ba67fEB",
"txHash": "0xde7a964526cf7350a7db5161accda12ff476a144c7967e485b123fc9590f6372",
"kind": "transparent"
},
{
"address": "0x70e0bA845a1A0F2DA3359C97E0285013525FFC49",
"txHash": "0x497a4bde97ccd2493c352dfb29fdebf160203b26f830c172c751dff0f9235c9e",
"kind": "transparent"
},
{
"address": "0x809d550fca64d94Bd9F66E60752A544199cfAC3D",
"txHash": "0x125796c5d629ab3bc171e86c1333e212e7aa17f76acdff1fd09b6378c3ae58d3",
"kind": "transparent"
}
],
"impls": {
"0002ac5494978eaaa1493964bf66ede2d1c7b3ce9a72bb21df782f9879635dfd": {
"address": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
"txHash": "0xd686e808a73b1c19d894db70d18d7814f9f04523a843fc53ab8ea7d47444542c",
"layout": {
"storage": [
{
"contract": "Initializable",
"label": "_initialized",
"type": "t_bool",
"src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:39"
},
{
"contract": "Initializable",
"label": "_initializing",
"type": "t_bool",
"src": "@openzeppelin\\contracts-upgradeable\\proxy\\utils\\Initializable.sol:44"
},
{
"contract": "ContextUpgradeable",
"label": "__gap",
"type": "t_array(t_uint256)50_storage",
"src": "@openzeppelin\\contracts-upgradeable\\utils\\ContextUpgradeable.sol:31"
},
{
"contract": "OwnableUpgradeable",
"label": "_owner",
"type": "t_address",
"src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:22"
},
{
"contract": "OwnableUpgradeable",
"label": "__gap",
"type": "t_array(t_uint256)49_storage",
"src": "@openzeppelin\\contracts-upgradeable\\access\\OwnableUpgradeable.sol:82"
},
{
"contract": "RocketJoeStakingContract",
"label": "moJOE",
"type": "t_contract(IERC20Upgradeable)277",
"src": "contracts\\RocketJoeStakingContract.sol:45"
},
{
"contract": "RocketJoeStakingContract",
"label": "lastRewardTimestamp",
"type": "t_uint256",
"src": "contracts\\RocketJoeStakingContract.sol:46"
},
{
"contract": "RocketJoeStakingContract",
"label": "accRJoePerShare",
"type": "t_uint256",
"src": "contracts\\RocketJoeStakingContract.sol:47"
},
{
"contract": "RocketJoeStakingContract",
"label": "rJOE",
"type": "t_contract(RocketJoeToken)2094",
"src": "contracts\\RocketJoeStakingContract.sol:50"
},
{
"contract": "RocketJoeStakingContract",
"label": "rJoePerSec",
"type": "t_uint256",
"src": "contracts\\RocketJoeStakingContract.sol:52"
},
{
"contract": "RocketJoeStakingContract",
"label": "userInfo",
"type": "t_mapping(t_address,t_struct(UserInfo)1587_storage)",
"src": "contracts\\RocketJoeStakingContract.sol:55"
}
],
"types": {
"t_contract(IERC20Upgradeable)277": {
"label": "contract IERC20Upgradeable"
},
"t_uint256": {
"label": "uint256"
},
"t_contract(RocketJoeToken)2094": {
"label": "contract RocketJoeToken"
},
"t_mapping(t_address,t_struct(UserInfo)1587_storage)": {
"label": "mapping(address => struct RocketJoeStakingContract.UserInfo)"
},
"t_address": {
"label": "address"
},
"t_struct(UserInfo)1587_storage": {
"label": "struct RocketJoeStakingContract.UserInfo",
"members": [
{
"label": "amount",
"type": "t_uint256"
},
{
"label": "rewardDebt",
"type": "t_uint256"
}
]
},
"t_array(t_uint256)49_storage": {
"label": "uint256[49]"
},
"t_array(t_uint256)50_storage": {
"label": "uint256[50]"
},
"t_bool": {
"label": "bool"
}
}
}
}
}
}
162 changes: 162 additions & 0 deletions contracts/RocketJoeStakingContract.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import "./RocketJoeToken.sol";

import "hardhat/console.sol";

// MasterChefJoe is a boss. He says "go f your blocks lego boy, I'm gonna use timestamp instead".
// And to top it off, it takes no risks. Because the biggest risk is operator error.
// So we make it virtually impossible for the operator of this contract to cause a bug with people's harvests.
//
// Note that it's ownable and the owner wields tremendous power. The ownership
// will be transferred to a governance smart contract once JOE is sufficiently
// distributed and the community can show to govern itself.
//
// With thanks to the Lydia Finance team.
//
// Godspeed and may the 10x be with you.
contract RocketJoeStakingContract is Initializable, OwnableUpgradeable {
using SafeERC20Upgradeable for IERC20Upgradeable;

// Info of each user.
struct UserInfo {
uint256 amount; // How many moJOE tokens the user has provided.
uint256 rewardDebt; // Reward debt. See explanation below.
//
// We do some fancy math here. Basically, any point in time, the amount of JOEs
// entitled to a user but is pending to be distributed is:
//
// pending reward = (user.amount * accRJoePerShare) - user.rewardDebt
//
// Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens:
// 1. `accRJoePerShare` (and `lastRewardTimestamp`) gets updated.
// 2. User receives the pending reward sent to his/her address.
// 3. User's `amount` gets updated.
// 4. User's `rewardDebt` gets updated.
}

// Info.
IERC20Upgradeable moJOE; // Address of moJOE token contract.
uint256 lastRewardTimestamp; // Last timestamp that rJOEs distribution occurs.
uint256 accRJoePerShare; // Accumulated JOEs per share, times 1e12. See below.

// The rJOE TOKEN!
RocketJoeToken public rJOE;
// rJOE tokens created per second.
uint256 public rJoePerSec;

// Info of each user that stakes LP tokens.
mapping(address => UserInfo) public userInfo;

event Deposit(address indexed user, uint256 amount);
event Withdraw(address indexed user, uint256 amount);
event EmergencyWithdraw(address indexed user, uint256 amount);
event UpdateEmissionRate(address indexed user, uint256 _rJoePerSec);

function initialize(IERC20Upgradeable _moJOE, RocketJoeToken _rJOE, uint256 _rJoePerSec) public initializer {
__Ownable_init();

moJOE = _moJOE;
rJOE = _rJOE;
rJoePerSec = _rJoePerSec;
}

// View function to see pending JOEs on frontend.
function pendingRJoe(address _user) external view returns (uint256) {
UserInfo storage user = userInfo[_user];
uint256 moJoeSupply = moJOE.balanceOf(address(this));
uint256 _accRJoePerShare = accRJoePerShare;

if (block.timestamp > lastRewardTimestamp && moJoeSupply != 0) {
uint256 multiplier = block.timestamp - lastRewardTimestamp;
uint256 rJoeReward = multiplier * rJoePerSec;
_accRJoePerShare = _accRJoePerShare + rJoeReward * 1e12 / moJoeSupply;
}
return user.amount * _accRJoePerShare / 1e12 - user.rewardDebt;
}

// Update reward variables of the given pool to be up-to-date.
function updatePool() public {
if (block.timestamp <= lastRewardTimestamp) {
return;
}
uint256 moJoeSupply = moJOE.balanceOf(address(this));
if (moJoeSupply == 0) {
lastRewardTimestamp = block.timestamp;
return;
}
uint256 multiplier = block.timestamp - lastRewardTimestamp;
uint256 rJoeReward = multiplier * rJoePerSec;
accRJoePerShare = accRJoePerShare + rJoeReward * 1e12 / moJoeSupply;
lastRewardTimestamp = block.timestamp;

rJOE.mint(address(this), rJoeReward);
}

// Deposit moJOE to RocketJoeStakingContract for rJOE allocation.
function deposit(uint256 _amount) public {
UserInfo storage user = userInfo[msg.sender];

updatePool();
if (user.amount > 0) {
uint256 pending = user.amount * accRJoePerShare / 1e12 - user.rewardDebt;
safeRJoeTransfer(msg.sender, pending);
}
user.amount = user.amount + _amount;
user.rewardDebt = user.amount * accRJoePerShare / 1e12;

moJOE.safeTransferFrom(address(msg.sender), address(this), _amount);
emit Deposit(msg.sender, _amount);
}

// Withdraw moJOE from RocketJoeStakingContract.
function withdraw(uint256 _amount) public {
UserInfo storage user = userInfo[msg.sender];
require(user.amount >= _amount, "withdraw: not good");

updatePool();
uint256 pending = user.amount * accRJoePerShare / 1e12 - user.rewardDebt;
user.amount = user.amount - _amount;
user.rewardDebt = user.amount * accRJoePerShare / 1e12;

safeRJoeTransfer(msg.sender, pending);
moJOE.safeTransfer(address(msg.sender), _amount);
emit Withdraw(msg.sender, _amount);
}

// Withdraw without caring about rewards. EMERGENCY ONLY.
function emergencyWithdraw() public {
UserInfo storage user = userInfo[msg.sender];

uint256 _amount = user.amount;
user.amount = 0;
user.rewardDebt = 0;

moJOE.safeTransfer(address(msg.sender), _amount);
emit EmergencyWithdraw(msg.sender, _amount);
}

// Safe rJoe transfer function, just in case if rounding error causes pool to not have enough JOEs.
function safeRJoeTransfer(address _to, uint256 _amount) internal {
uint256 rJoeBal = rJOE.balanceOf(address(this));
if (_amount > rJoeBal) {
rJOE.transfer(_to, rJoeBal);
} else {
rJOE.transfer(_to, _amount);
}
}

// Pancake has to add hidden dummy pools inorder to alter the emission,
// here we make it simple and transparent to all.
function updateEmissionRate(uint256 _rJoePerSec) public onlyOwner {
updatePool();
rJoePerSec = _rJoePerSec;
emit UpdateEmissionRate(msg.sender, _rJoePerSec);
}
}
16 changes: 16 additions & 0 deletions contracts/RocketJoeToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

// RocketJoeToken, rJoe.
contract RocketJoeToken is ERC20("RocketJoeToken", "rJOE"), Ownable {
/// @notice Infinite supply, but burned to join IDO.

/// @notice Creates `_amount` token to `_to`. Must only be called by the owner (RocketJoeStakingContract).
function mint(address _to, uint256 _amount) public onlyOwner {
_mint(_to, _amount);
}
}
Loading

0 comments on commit 06f2397

Please sign in to comment.