github.com/codingfuture/orig-energi3@v0.8.4/energi/contracts/src/MasternodeTokenV1.sol (about) 1 // Copyright 2019 The Energi Core Authors 2 // This file is part of Energi Core. 3 // 4 // Energi Core is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Energi Core is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Energi Core. If not, see <http://www.gnu.org/licenses/>. 16 17 // Energi Governance system is the fundamental part of Energi Core. 18 19 // NOTE: It's not allowed to change the compiler due to byte-to-byte 20 // match requirement. 21 pragma solidity 0.5.16; 22 //pragma experimental SMTChecker; 23 24 import { GlobalConstants } from "./constants.sol"; 25 import { IGovernedContract, GovernedContract } from "./GovernedContract.sol"; 26 import { IGovernedProxy } from "./IGovernedProxy.sol"; 27 import { IMasternodeToken } from "./IMasternodeToken.sol"; 28 import { IMasternodeRegistry } from "./IMasternodeRegistry.sol"; 29 import { NonReentrant } from "./NonReentrant.sol"; 30 import { StorageBase } from "./StorageBase.sol"; 31 32 /** 33 * Permanent storage of Masternode Token V1 data. 34 */ 35 contract StorageMasternodeTokenV1 is 36 StorageBase 37 { 38 struct Balance { 39 uint256 amount; 40 uint256 last_block; 41 } 42 mapping(address => Balance) public balances; 43 44 // NOTE: ABIEncoderV2 is not acceptable at the moment of development! 45 function balanceOnly(address _account) 46 external view 47 returns(uint256 amount) 48 { 49 return balances[_account].amount; 50 } 51 52 function setBalance(address _account, uint256 _amount, uint256 _last_block) 53 external 54 requireOwner 55 { 56 // NOTE: DO NOT process last_block as part of storage logic! 57 Balance storage item = balances[_account]; 58 item.amount = _amount; 59 item.last_block = _last_block; 60 } 61 } 62 63 /** 64 * MN-1: Genesis hardcoded version of MasternodeToken. 65 * 66 * NOTE: it MUST NOT change after blockchain launch! 67 */ 68 contract MasternodeTokenV1 is 69 GlobalConstants, 70 GovernedContract, 71 IMasternodeToken, 72 NonReentrant 73 { 74 // Data for migration 75 //--------------------------------- 76 StorageMasternodeTokenV1 public v1storage; 77 IGovernedProxy public registry_proxy; 78 //--------------------------------- 79 80 constructor(address _proxy, IGovernedProxy _registry_proxy) 81 public 82 GovernedContract(_proxy) 83 { 84 v1storage = new StorageMasternodeTokenV1(); 85 registry_proxy = _registry_proxy; 86 87 // ERC20 88 emit Transfer(address(0), address(0), 0); 89 } 90 91 // IGovernedContract 92 //--------------------------------- 93 function _destroy(IGovernedContract _newImpl) internal { 94 v1storage.setOwner(_newImpl); 95 } 96 97 // MasternodeTokenV1 98 //--------------------------------- 99 100 function totalSupply() external view returns (uint256) { 101 return address(this).balance; 102 } 103 104 function name() external view returns (string memory) { 105 return "Masternode Collateral"; 106 } 107 108 function symbol() external view returns (string memory) { 109 return "MNGR"; 110 } 111 112 function decimals() external view returns (uint8) { 113 return 18 + 4; 114 } 115 116 function balanceOf(address _owner) external view returns (uint256) { 117 return v1storage.balanceOnly(_owner); 118 } 119 120 function transfer(address, uint256) external returns (bool) { 121 revert("Not allowed"); 122 } 123 124 function transferFrom(address, address, uint256) external returns (bool) { 125 revert("Not allowed"); 126 } 127 128 function approve(address, uint256) external returns (bool) { 129 revert("Not allowed"); 130 } 131 132 function allowance(address, address) external view returns (uint256) { 133 return 0; 134 } 135 136 // Energi 137 //--------------------------------- 138 139 // solium-disable security/no-block-members 140 141 function balanceInfo(address _tokenOwner) 142 external view 143 returns (uint256 balance, uint256 last_block) 144 { 145 (balance, last_block) = v1storage.balances(_tokenOwner); 146 } 147 148 function withdrawCollateral(uint256 _amount) external noReentry { 149 // Retrieve 150 address payable tokenOwner = _callerAddress(); 151 uint256 balance = v1storage.balanceOnly(tokenOwner); 152 153 // Process 154 if (balance < _amount) { 155 revert("Not enough"); 156 } 157 158 balance -= _amount; 159 _validateBalance(balance); 160 161 // Store 162 v1storage.setBalance(tokenOwner, balance, block.number); 163 164 // Events 165 emit Transfer(tokenOwner, address(0), _amount); 166 167 // Notify the registry 168 IMasternodeRegistry(address(registry_proxy.impl())).onCollateralUpdate(tokenOwner); 169 170 // TODO: we may need to allow more gas here for shared masternode contracts! 171 tokenOwner.transfer(_amount); 172 } 173 174 function depositCollateral() external payable noReentry { 175 // Retrieve 176 address payable tokenOwner = _callerAddress(); 177 uint256 balance = v1storage.balanceOnly(tokenOwner); 178 179 // Process 180 balance += msg.value; 181 _validateBalance(balance); 182 183 // Store 184 v1storage.setBalance(tokenOwner, balance, block.number); 185 186 // Events 187 emit Transfer(address(0), tokenOwner, msg.value); 188 189 // Notify the registry 190 IMasternodeRegistry(address(registry_proxy.impl())).onCollateralUpdate(tokenOwner); 191 } 192 193 function _validateBalance(uint256 _amount) internal pure { 194 // NOTE: "Too small" check makes no sense as it would be just zero. 195 196 if (_amount > MN_COLLATERAL_MAX) { 197 revert("Too much"); 198 } 199 200 if ((_amount % MN_COLLATERAL_MIN) != 0) { 201 revert("Not a multiple"); 202 } 203 } 204 205 // Safety 206 //--- 207 function () external payable { 208 revert("Not supported"); 209 } 210 }