/mail/ez-pine-gpg/

s-git' href='https://www.csie.ntu.edu.tw/~b01902062/git/tangerine-node-staker' title='tangerine-node-staker Git repository'/>
aboutsummaryrefslogtreecommitdiffstats
path: root/contracts/NodeStaker.sol
blob: 9ebeafc2b496a0f9546fc6ff67e243fc12223e1d (plain) (blame)
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
pragma solidity ^0.5.11;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "./Governance.sol";
import "./FoundationOwnable.sol";

contract NodeStaker is Ownable, FoundationOwnable {

  using SafeMath for uint256;

  Governance gov = Governance(0x246FcDE58581e2754f215A523C0718C4BFc8041F);
  bool public registered;
  uint256 public vested;
  uint256 public availableUnstakeAmount;

  // ------
  // Events
  // ------

  event NodeRegister(
    address sender,
    bytes publicKey,
    string name,
    string email,
    string location,
    string url,
    uint256 value
  );
  event NodeDeposited(address sender, uint256 amount);
  event NodeVested(uint256 amount);
  event NodeWithdrawn(address owner, uint256 amount);
  event NodePublicKeyReplaced(bytes oldKey, bytes newKey);
  event UnstakedByFoundation(uint256 amount);
  event OwnershipTranferedByFoundation(address from, address to);

  // ---------
  // Modifiers
  // ---------

  modifier onlyRegistered() {
    require(registered, "not registered yet");
    _;
  }

  /**
    * @notice funds from non-governance source will be prorated refund to foundation
    */
  function () external payable {
    emit NodeDeposited(msg.sender, msg.value);
  }

  // -------------------
  // Getters and Setters
  // -------------------
  function getStakedAmount() public view returns (uint256) {
    uint256 offset = uint256(gov.nodesOffsetByAddress(address(this)));
    uint256 staked;
    (,,staked,,,,,,,) = gov.nodes(offset);
    return staked;
  }

  function getUnstakedAmount() public view returns (uint256) {
    uint256 offset = uint256(gov.nodesOffsetByAddress(address(this)));
    uint256 unstaked;
    (,,,,,,,,unstaked,) = gov.nodes(offset);
    return unstaked;
  }

  // ------------------------
  // Node Operation Functions
  // ------------------------

  /**
    * @dev register a node
    */
  function register(
    bytes memory publicKey,
    string memory name,
    string memory email,
    string memory location,
    string memory url
  ) public onlyOwner {
    require(!registered, "already registered");
    uint256 minStake = gov.minStake();
    gov.register.value(minStake)(publicKey, name, email, location, url);
    registered = true;
    emit NodeRegister(msg.sender, publicKey, name, email, location, url, minStake);
  }

  /**
    * @dev withdraw balance
    */
  function withdraw() public onlyOwner onlyRegistered {
    if (gov.withdrawable()) gov.withdraw();
    uint256 amount = address(this).balance;
    msg.sender.transfer(amount);
    emit NodeWithdrawn(msg.sender, amount);
  }

  /**
    * @dev replace node public key
    */
  function replaceNodePublicKey(bytes memory key) public onlyOwner onlyRegistered {
    bytes memory oldKey;
    uint256 offset = uint256(gov.nodesOffsetByAddress(address(this)));
    (,oldKey,,,,,,,,) = gov.nodes(offset);
    gov.replaceNodePublicKey(key);
    emit NodePublicKeyReplaced(oldKey, key);
  }

  // -------------------------
  // Foundation Only Functions
  // -------------------------

  /**
    * @dev transfer node ownership
    */
  function transferOwnershipByFoundation(address newOwner) public onlyFoundation {
    address oldOwner = owner();
    _transferOwnership(newOwner);
    emit OwnershipTranferedByFoundation(oldOwner, newOwner);
  }

  /**
    * @dev unstake by foundation
    * @notice only can unstake vested amount
    */
  function unstakeByFoundation(uint256 amount) public onlyFoundation onlyRegistered {
    require(amount <= availableUnstakeAmount, "unstaking amount should not be greater than availableUnstakeAmount.");
    availableUnstakeAmount.sub(amount);
    gov.unstake(amount);
    emit UnstakedByFoundation(amount);
  }

  /**
    * @dev vest
    */
  function vest(uint256 amount) public onlyFoundation onlyRegistered {
    vested = vested.add(amount); 
    availableUnstakeAmount = availableUnstakeAmount.add(amount);
    emit NodeVested(amount);
  }
}