Skip to content

Commit

Permalink
fix #11
Browse files Browse the repository at this point in the history
  • Loading branch information
hujw77 committed Jun 7, 2024
1 parent a5b90d5 commit 668cab4
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 55 deletions.
19 changes: 11 additions & 8 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,6 @@ contract DeployScript is Script {
"Deposit.sol:Deposit", multisig, abi.encodeCall(Deposit.initialize, ("RING Deposit NFT", "RDPS"))
);

address hub = Upgrades.deployTransparentProxy(
"CollatorStakingHub.sol:CollatorStakingHub",
multisig,
abi.encodeCall(CollatorStakingHub.initialize, (deposit, "RING"))
);

uint256 minDelay = 3 days;
address timelock = Upgrades.deployTransparentProxy(
"RingTimelockController.sol:RingTimelockController",
Expand All @@ -40,7 +34,7 @@ contract DeployScript is Script {
address gRING = Upgrades.deployTransparentProxy(
"GovernanceRing.sol:GovernanceRing",
timelock,
abi.encodeCall(GovernanceRing.initialize, (deposit, hub, "Governance RING", "gRING"))
abi.encodeCall(GovernanceRing.initialize, (multisig, deposit, "Governance RING", "gRING"))
);

address ringDAO = Upgrades.deployTransparentProxy(
Expand All @@ -50,7 +44,16 @@ contract DeployScript is Script {
RingDAO.initialize, (IVotes(gRING), TimelockControllerUpgradeable(payable(timelock)), "RingDAO")
)
);
// RingTimelockController(timelock).granRole(RingTimelockController(timelock).PROPOSER_ROLE, ringDAO);

address hub = Upgrades.deployTransparentProxy(
"CollatorStakingHub.sol:CollatorStakingHub",
timelock,
abi.encodeCall(CollatorStakingHub.initialize, (gRING, deposit, "RING"))
);

// RingTimelockController(timelock).grantRole(RingTimelockController(timelock).PROPOSER_ROLE(), ringDAO);
// RingTimelockController(gRING).grantRole(GovernanceRing(gRING).MINTER_ROLE(), hub);
// RingTimelockController(gRING).grantRole(GovernanceRing(gRING).BURNER_ROLE(), hub);

vm.stopBroadcast();
}
Expand Down
30 changes: 15 additions & 15 deletions src/collator/CollatorSet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ abstract contract CollatorSet is Initializable, CollatorStakingHubStorage {
address private constant HEAD = address(0x1);
address private constant TAIL = address(0x2);

event AddCollator(address indexed cur, uint256 score, address prev);
event AddCollator(address indexed cur, uint256 votes, address prev);
event RemoveCollator(address indexed cur, address prev);
event UpdateCollator(address indexed cur, uint256 score, address oldPrev, address newPrev);
event UpdateCollator(address indexed cur, uint256 votes, address oldPrev, address newPrev);

function __CollatorSet_init() internal onlyInitializing {
collators[HEAD] = collators[TAIL];
Expand All @@ -33,19 +33,19 @@ abstract contract CollatorSet is Initializable, CollatorStakingHubStorage {
return c != address(0) && c != HEAD && c != TAIL;
}

function _addCollator(address cur, uint256 score, address prev) internal {
function _addCollator(address cur, uint256 votes, address prev) internal {
require(_isValid(cur), "!valid");
address next = collators[prev];
// No duplicate collator allowed.
require(collators[cur] == address(0), "!cur");
// Next collaotr must in the list.
require(next != address(0), "!prev");
require(_verifyIndex(prev, score, next), "!score");
require(_verifyIndex(prev, votes, next), "!votes");
collators[cur] = next;
collators[prev] = cur;
votesOf[cur] = score;
votesOf[cur] = votes;
count++;
emit AddCollator(cur, score, prev);
emit AddCollator(cur, votes, prev);
}

function _removeCollator(address cur, address prev) internal {
Expand All @@ -59,28 +59,28 @@ abstract contract CollatorSet is Initializable, CollatorStakingHubStorage {
emit RemoveCollator(cur, prev);
}

function _increaseScore(address cur, uint256 score, address oldPrev, address newPrev) internal {
_updateScore(cur, votesOf[cur] + score, oldPrev, newPrev);
function _increaseVotes(address cur, uint256 votes, address oldPrev, address newPrev) internal {
_updateVotes(cur, votesOf[cur] + votes, oldPrev, newPrev);
}

function _reduceScore(address cur, uint256 score, address oldPrev, address newPrev) internal {
_updateScore(cur, votesOf[cur] - score, oldPrev, newPrev);
function _reduceVotes(address cur, uint256 votes, address oldPrev, address newPrev) internal {
_updateVotes(cur, votesOf[cur] - votes, oldPrev, newPrev);
}

function _updateScore(address cur, uint256 newScore, address oldPrev, address newPrev) internal {
function _updateVotes(address cur, uint256 newVotes, address oldPrev, address newPrev) internal {
require(_isValid(cur), "!valid");
require(collators[cur] != address(0), "!cur");
require(collators[oldPrev] != address(0), "!oldPrev");
require(collators[newPrev] != address(0), "!newPrev");
if (oldPrev == newPrev) {
require(_isPrevCollator(cur, oldPrev), "!oldPrev");
require(_verifyIndex(newPrev, newScore, collators[cur]), "!score");
votesOf[cur] = newScore;
require(_verifyIndex(newPrev, newVotes, collators[cur]), "!votes");
votesOf[cur] = newVotes;
} else {
_removeCollator(cur, oldPrev);
_addCollator(cur, newScore, newPrev);
_addCollator(cur, newVotes, newPrev);
}
emit UpdateCollator(cur, newScore, oldPrev, newPrev);
emit UpdateCollator(cur, newVotes, oldPrev, newPrev);
}

// prev >= cur >= next
Expand Down
27 changes: 15 additions & 12 deletions src/collator/CollatorStakingHub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "./interfaces/ICollatorStakingPool.sol";
import "./interfaces/IGRING.sol";
import "../deposit/interfaces/IDeposit.sol";
import "./CollatorStakingPool.sol";
import "./CollatorSet.sol";
Expand All @@ -18,7 +19,9 @@ contract CollatorStakingHub is Initializable, ReentrancyGuardUpgradeable, Collat
using Address for address payable;
using EnumerableSet for EnumerableSet.UintSet;

// Staking Pallet Account
// The lock-up period starts with the stake or inscrease stake.
uint256 public constant LOCK_PERIOD = 1 days;
// Staking Pallet Account.
address public constant STAKING_PALLET = 0x6D6F646C64612f7374616B690000000000000000;
// 0 ~ 100
uint256 private constant COMMISSION_BASE = 100;
Expand All @@ -33,7 +36,8 @@ contract CollatorStakingHub is Initializable, ReentrancyGuardUpgradeable, Collat
_;
}

function initialize(address dps, string memory symbol) public initializer {
function initialize(address gring, address dps, string memory symbol) public initializer {
gRING = gring;
DEPOSIT = dps;
SYMBOL = symbol;
__ReentrancyGuard_init();
Expand All @@ -54,13 +58,8 @@ contract CollatorStakingHub is Initializable, ReentrancyGuardUpgradeable, Collat
require(poolOf[collator] == address(0), "created");

uint256 index = count;
string memory indexStr = index.toString();
string memory tmp = string.concat(string.concat(SYMBOL, "-"), indexStr);
string memory name = string.concat("Collator Staking ", tmp);
string memory symbol = string.concat("st", tmp);

bytes memory bytecode = type(CollatorStakingPool).creationCode;
bytes memory initCode = bytes.concat(bytecode, abi.encode(collator, name, symbol));
bytes memory initCode = bytes.concat(bytecode, abi.encode(collator, index));
assembly {
pool := create2(0, add(initCode, 32), mload(initCode), 0)
}
Expand All @@ -75,15 +74,19 @@ contract CollatorStakingHub is Initializable, ReentrancyGuardUpgradeable, Collat
}

function _stake(address collator, address account, uint256 assets) internal {
stakingLocks[collator][account] = LOCK_PERIOD + block.timestamp;
address pool = poolOf[collator];
require(pool != address(0), "!collator");
ICollatorStakingPool(pool).stake(account, assets);
IGRING(gRING).mint(account, assets);
emit Staked(pool, collator, account, assets);
}

function _unstake(address collator, address account, uint256 assets) internal {
require(stakingLocks[collator][account] < block.timestamp, "!locked");
address pool = poolOf[collator];
require(pool != address(0), "!collator");
IGRING(gRING).burn(account, assets);
ICollatorStakingPool(pool).withdraw(account, assets);
emit Unstaked(pool, collator, account, assets);
}
Expand All @@ -96,14 +99,14 @@ contract CollatorStakingHub is Initializable, ReentrancyGuardUpgradeable, Collat

function stakeRING(address collator, address oldPrev, address newPrev) public payable nonReentrant {
_stake(collator, msg.sender, msg.value);
_increaseScore(collator, _assetsToVotes(commissionOf[collator], msg.value), oldPrev, newPrev);
_increaseVotes(collator, _assetsToVotes(commissionOf[collator], msg.value), oldPrev, newPrev);
stakedRINGOf[msg.sender] += msg.value;
}

function unstakeRING(address collator, uint256 assets, address oldPrev, address newPrev) public nonReentrant {
_unstake(collator, msg.sender, assets);
payable(msg.sender).sendValue(assets);
_reduceScore(collator, _assetsToVotes(commissionOf[collator], assets), oldPrev, newPrev);
_reduceVotes(collator, _assetsToVotes(commissionOf[collator], assets), oldPrev, newPrev);
stakedRINGOf[msg.sender] -= assets;
}

Expand All @@ -114,7 +117,7 @@ contract CollatorStakingHub is Initializable, ReentrancyGuardUpgradeable, Collat
depositInfos[depositId] = DepositInfo(account, assets, collator);

_stake(collator, account, assets);
_increaseScore(collator, _assetsToVotes(commissionOf[collator], assets), oldPrev, newPrev);
_increaseVotes(collator, _assetsToVotes(commissionOf[collator], assets), oldPrev, newPrev);
require(_stakedDeposits[account].add(depositId), "!add");
}

Expand All @@ -126,7 +129,7 @@ contract CollatorStakingHub is Initializable, ReentrancyGuardUpgradeable, Collat
delete depositInfos[depositId];

_unstake(info.collator, info.account, info.assets);
_reduceScore(info.collator, _assetsToVotes(commissionOf[info.collator], info.assets), oldPrev, newPrev);
_reduceVotes(info.collator, _assetsToVotes(commissionOf[info.collator], info.assets), oldPrev, newPrev);
require(_stakedDeposits[account].remove(depositId), "!remove");
}

Expand Down
4 changes: 4 additions & 0 deletions src/collator/CollatorStakingHubStorage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ contract CollatorStakingHubStorage {
mapping(address => uint256) public votesOf;

// ---------------------- CollatorStakingHubStorage ---------------------
// Governance RING
address public gRING;
// Deposit NFT.
address public DEPOSIT;
// CollatorStakingPool symbol subfix
Expand All @@ -23,6 +25,8 @@ contract CollatorStakingHubStorage {
mapping(address => address) public collatorOf;
// collator => commission
mapping(address => uint256) public commissionOf;
// collator => user => lockTime
mapping(address => mapping(address => uint256)) public stakingLocks;
// user => staked ring
mapping(address => uint256) public stakedRINGOf;
// user => staked depositIds
Expand Down
4 changes: 3 additions & 1 deletion src/collator/CollatorStakingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ contract CollatorStakingPool {

/* ========== STATE VARIABLES ========== */

uint256 public id;
address public hub;
address public collator;
uint256 public periodFinish = 0;
Expand All @@ -30,9 +31,10 @@ contract CollatorStakingPool {

/* ========== CONSTRUCTOR ========== */

constructor(address collator_) {
constructor(address collator_, uint256 index) {
hub = msg.sender;
collator = collator_;
id = index;
}

/* ========== VIEWS ========== */
Expand Down
9 changes: 9 additions & 0 deletions src/collator/interfaces/IGRING.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.24;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IGRING is IERC20 {
function burn(address from, uint256 amount) external returns (bool);
function mint(address to, uint256 amount) external returns (bool);
}
35 changes: 16 additions & 19 deletions src/governance/GovernanceRing.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ pragma solidity 0.8.20;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20VotesUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "../collator/interfaces/ICollatorStakingHub.sol";
import "../deposit/interfaces/IDeposit.sol";

contract GovernanceRing is
Initializable,
ERC20Upgradeable,
AccessControlUpgradeable,
ERC20PermitUpgradeable,
ERC20VotesUpgradeable,
ReentrancyGuardUpgradeable
Expand All @@ -28,35 +29,41 @@ contract GovernanceRing is
mapping(address => mapping(address => uint256)) public wrapAssets;
// user => wrap depositIds
mapping(address => EnumerableSet.UintSet) private _wrapDeposits;
ICollatorStakingHub public HUB;
IDeposit public DEPOSIT;

address public constant RING = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");

event Wrap(address indexed account, address indexed token, uint256 assets);
event Unwrap(address indexed account, address indexed token, uint256 assets);
event WrapDeposit(address indexed account, address indexed token, uint256 depositId);
event UnwrapDeposit(address indexed account, address indexed token, uint256 depositId);

modifier onlySTRING(address token) {
require(HUB.exist(token), "!stRING");
_;
}

function initialize(address dps, address hub, string memory name, string memory symbol) public initializer {
function initialize(address admin, address dps, string memory name, string memory symbol) public initializer {
DEPOSIT = IDeposit(dps);
HUB = ICollatorStakingHub(hub);
__ERC20_init(name, symbol);
__AccessControl_init();
__ERC20Permit_init(symbol);
__ERC20Votes_init();
__ReentrancyGuard_init();

_grantRole(DEFAULT_ADMIN_ROLE, admin);
}

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

function mint(address to, uint256 assets) public onlyRole(MINTER_ROLE) {
_mint(to, assets);
}

function burn(address from, uint256 assets) public onlyRole(BURNER_ROLE) {
_burn(from, assets);
}

function _wrap(address account, address token, uint256 assets) internal {
_mint(account, assets);
wrapAssets[account][token] += assets;
Expand All @@ -78,16 +85,6 @@ contract GovernanceRing is
payable(msg.sender).sendValue(assets);
}

function wrapCRING(address cring, uint256 assets) external onlySTRING(cring) nonReentrant {
IERC20(cring).transferFrom(msg.sender, address(this), assets);
_wrap(msg.sender, cring, assets);
}

function unwrapCRING(address cring, uint256 assets) external onlySTRING(cring) nonReentrant {
_unwrap(msg.sender, cring, assets);
IERC20(cring).transferFrom(address(this), msg.sender, assets);
}

function wrapDeposit(uint256 depositId) public nonReentrant {
address account = msg.sender;
DEPOSIT.transferFrom(account, address(this), depositId);
Expand Down

0 comments on commit 668cab4

Please sign in to comment.