Skip to content

Commit 633b896

Browse files
authored
Merge branch 'dev' into feature/astradex-ecosystem-contracts
2 parents 16f3edd + 14d6326 commit 633b896

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+7541
-557
lines changed

.openzeppelin/unknown-16718.json

Lines changed: 710 additions & 0 deletions
Large diffs are not rendered by default.

.openzeppelin/unknown-22040.json

Lines changed: 1191 additions & 0 deletions
Large diffs are not rendered by default.

.openzeppelin/unknown-30746.json

Lines changed: 525 additions & 53 deletions
Large diffs are not rendered by default.
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
//SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.0;
3+
4+
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
5+
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
6+
import "../../consensus/IValidatorSet.sol";
7+
import "../../funds/RewardsBank.sol";
8+
import "../../finance/Treasury.sol";
9+
import "./LiquidPool.sol";
10+
import "../../utils/TransferViaCall.sol";
11+
12+
contract LiquidNodesManager is UUPSUpgradeable, AccessControlUpgradeable {
13+
bytes32 constant public BACKEND_ROLE = keccak256("BACKEND_ROLE");
14+
bytes32 constant public POOL_ROLE = keccak256("POOL_ROLE");
15+
16+
IValidatorSet public validatorSet;
17+
RewardsBank public rewardsBank;
18+
19+
address public treasury;
20+
Treasury public treasuryFee;
21+
22+
uint public nodeStake; // stake for 1 onboarded node
23+
uint public maxNodesCount;
24+
address[] public nodes;
25+
uint private _totalNodesStake;
26+
27+
uint private _requestId;
28+
uint private _requestStake;
29+
uint256[10] __gap;
30+
31+
32+
event AddNodeRequest(uint indexed requestId, uint indexed nodeId, uint stake);
33+
event NodeOnboarded(uint indexed requestId, address indexed node, uint indexed nodeId, uint stake);
34+
event RequestFailed(uint indexed requestId, uint indexed nodeId, uint stake);
35+
event NodeRetired(uint indexed nodeId, address indexed node, uint stake);
36+
event Reward(address indexed addr, uint amount);
37+
38+
function initialize(
39+
IValidatorSet validatorset_, RewardsBank rewardsBank_,
40+
address treasury_, Treasury treasuryFee_,
41+
uint nodeStake_, uint maxNodesCount_
42+
) public initializer {
43+
validatorSet = validatorset_;
44+
rewardsBank = rewardsBank_;
45+
treasury = treasury_;
46+
treasuryFee = treasuryFee_;
47+
nodeStake = nodeStake_;
48+
maxNodesCount = maxNodesCount_;
49+
nodes = new address[](0);
50+
__AccessControl_init();
51+
_setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
52+
}
53+
54+
// POOL METHODS
55+
56+
function stake() external payable onlyRole(POOL_ROLE) {
57+
// retire node if maxNodesCount was changed
58+
if (nodes.length > maxNodesCount) {
59+
_retireNode();
60+
}
61+
// try to onboard new node
62+
_requestNodeCreation();
63+
}
64+
65+
function unstake(uint amount) external onlyRole(POOL_ROLE) {
66+
// retire node if not enough free balance
67+
while (getFreeBalance() < amount) {
68+
_retireNode();
69+
}
70+
transferViaCall(payable(msg.sender), amount);
71+
// Try to onboard new node in case if maxNodesCount was changed
72+
_requestNodeCreation();
73+
}
74+
// IStakeManager impl
75+
76+
function reward(address nodeAddress, uint256 amount) public {
77+
require(msg.sender == address(validatorSet), "Only validatorSet can call reward()");
78+
79+
uint feeAmount = treasuryFee.calcFee(amount);
80+
rewardsBank.withdrawAmb(payable(address(treasuryFee)), feeAmount);
81+
amount -= feeAmount;
82+
83+
rewardsBank.withdrawAmb(payable(treasury), amount);
84+
validatorSet.emitReward(address(rewardsBank), nodeAddress, address(this), address(treasury), address(0), amount);
85+
}
86+
87+
function report(address nodeAddress) public {}
88+
89+
// BAKEND METHODS
90+
91+
function onboardNode(uint requestId, address node, uint nodeId) public onlyRole(BACKEND_ROLE) {
92+
_onboardNode(requestId, node, nodeId);
93+
}
94+
95+
// ADMIN METHODS
96+
97+
function setNodeStakeAndCount(uint nodeStake_, uint maxNodesCount_) public onlyRole(DEFAULT_ADMIN_ROLE) {
98+
nodeStake = nodeStake_;
99+
maxNodesCount = maxNodesCount_;
100+
}
101+
102+
// INTERNAL METHODS
103+
104+
function _authorizeUpgrade(address newImplementation) internal override onlyRole(DEFAULT_ADMIN_ROLE) {}
105+
106+
function _onboardNode(uint requestId, address node, uint nodeId) private {
107+
require(node != address(0), "Node address can't be zero");
108+
require(_requestStake > 0, "No active request");
109+
require(validatorSet.getNodeStake(node) == 0, "Node already onboarded");
110+
require(requestId == _requestId, "Invalid request id");
111+
require(address(this).balance >= _totalNodesStake + _requestStake, "Not enough balance");
112+
113+
if (nodeId == nodes.length && getFreeBalance() >= _requestStake) {
114+
nodes.push(node);
115+
_totalNodesStake += _requestStake;
116+
validatorSet.newStake(node, _requestStake, true);
117+
emit NodeOnboarded(requestId, node, nodeId, _requestStake);
118+
} else {
119+
emit RequestFailed(requestId, nodeId, _requestStake);
120+
}
121+
122+
_requestStake = 0;
123+
124+
// try to onboard another node
125+
_requestNodeCreation();
126+
}
127+
128+
function _retireNode() private {
129+
require(nodes.length > 0, "No nodes onboarded");
130+
131+
address node = nodes[nodes.length - 1];
132+
uint deposit = getNodeDeposit(node);
133+
_totalNodesStake -= deposit;
134+
nodes.pop();
135+
validatorSet.unstake(node, deposit);
136+
emit NodeRetired(nodes.length, node, deposit);
137+
}
138+
139+
function _requestNodeCreation() private {
140+
if (_requestStake == 0 && getFreeBalance() >= nodeStake && nodes.length < maxNodesCount) {
141+
_requestId++;
142+
_requestStake = nodeStake;
143+
emit AddNodeRequest(_requestId, nodes.length, _requestStake);
144+
}
145+
}
146+
147+
148+
function getNodeDeposit(address node) public view returns (uint) {
149+
return validatorSet.getNodeStake(node);
150+
}
151+
152+
function getNodesCount() public view returns (uint) {
153+
return nodes.length;
154+
}
155+
156+
function getNodes() public view returns (address[] memory) {
157+
return nodes;
158+
}
159+
160+
// balance that not used for nodes stakes
161+
function getFreeBalance() public view returns (uint) {
162+
return address(this).balance - _totalNodesStake;
163+
}
164+
}

0 commit comments

Comments
 (0)