MiniMeToken.sol
1 pragma solidity ^0.5.2; 2 3 /* 4 Copyright 2016, Jordi Baylina 5 This program is free software: you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation, either version 3 of the License, or 8 (at your option) any later version. 9 This program 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 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 /** 17 * @title MiniMeToken Contract 18 * @author Jordi Baylina 19 * @dev This token contract's goal is to make it easy for anyone to clone this 20 * token using the token distribution at a given block, this will allow DAO's 21 * and DApps to upgrade their features in a decentralized manner without 22 * affecting the original token 23 * @dev It is ERC20 compliant, but still needs to under go further testing. 24 */ 25 26 import "../common/Controlled.sol"; 27 import "./TokenController.sol"; 28 import "./ApproveAndCallFallBack.sol"; 29 import "./MiniMeTokenInterface.sol"; 30 import "./TokenFactory.sol"; 31 32 /** 33 * @dev The actual token contract, the default controller is the msg.sender 34 * that deploys the contract, so usually this token will be deployed by a 35 * token controller contract, which Giveth will call a "Campaign" 36 */ 37 38 39 contract MiniMeToken is MiniMeTokenInterface, Controlled { 40 41 string public name; //The Token's name: e.g. DigixDAO Tokens 42 uint8 public decimals; //Number of decimals of the smallest unit 43 string public symbol; //An identifier: e.g. REP 44 string public constant VERSION = "MMT_0.1"; //An arbitrary versioning scheme 45 46 /** 47 * @dev `Checkpoint` is the structure that attaches a block number to a 48 * given value, the block number attached is the one that last changed the 49 * value 50 */ 51 struct Checkpoint { 52 53 // `fromBlock` is the block number that the value was generated from 54 uint128 fromBlock; 55 56 // `value` is the amount of tokens at a specific block number 57 uint128 value; 58 } 59 60 // `parentToken` is the Token address that was cloned to produce this token; 61 // it will be 0x0 for a token that was not cloned 62 MiniMeToken public parentToken; 63 64 // `parentSnapShotBlock` is the block number from the Parent Token that was 65 // used to determine the initial distribution of the Clone Token 66 uint public parentSnapShotBlock; 67 68 // `creationBlock` is the block number that the Clone Token was created 69 uint public creationBlock; 70 71 // `balances` is the map that tracks the balance of each address, in this 72 // contract when the balance changes the block number that the change 73 // occurred is also included in the map 74 mapping (address => Checkpoint[]) balances; 75 76 // `allowed` tracks any extra transfer rights as in all ERC20 tokens 77 mapping (address => mapping (address => uint256)) allowed; 78 79 // Tracks the history of the `totalSupply` of the token 80 Checkpoint[] totalSupplyHistory; 81 82 // Flag that determines if the token is transferable or not. 83 bool public transfersEnabled; 84 85 // The factory used to create new clone tokens 86 TokenFactory public tokenFactory; 87 88 //////////////// 89 // Constructor 90 //////////////// 91 92 /** 93 * @notice Constructor to create a MiniMeToken 94 * @param _tokenFactory The address of the MiniMeTokenFactory contract that 95 * will create the Clone token contracts, the token factory needs to be 96 * deployed first 97 * @param _parentToken Address of the parent token, set to 0x0 if it is a 98 * new token 99 * @param _parentSnapShotBlock Block of the parent token that will 100 * determine the initial distribution of the clone token, set to 0 if it 101 * is a new token 102 * @param _tokenName Name of the new token 103 * @param _decimalUnits Number of decimals of the new token 104 * @param _tokenSymbol Token Symbol for the new token 105 * @param _transfersEnabled If true, tokens will be able to be transferred 106 */ 107 constructor( 108 address _tokenFactory, 109 address _parentToken, 110 uint _parentSnapShotBlock, 111 string memory _tokenName, 112 uint8 _decimalUnits, 113 string memory _tokenSymbol, 114 bool _transfersEnabled 115 ) 116 public 117 { 118 tokenFactory = TokenFactory(_tokenFactory); 119 name = _tokenName; // Set the name 120 decimals = _decimalUnits; // Set the decimals 121 symbol = _tokenSymbol; // Set the symbol 122 parentToken = MiniMeToken(address(uint160(_parentToken))); 123 parentSnapShotBlock = _parentSnapShotBlock; 124 transfersEnabled = _transfersEnabled; 125 creationBlock = block.number; 126 } 127 128 129 /////////////////// 130 // ERC20 Methods 131 /////////////////// 132 133 /** 134 * @notice Send `_amount` tokens to `_to` from `msg.sender` 135 * @param _to The address of the recipient 136 * @param _amount The amount of tokens to be transferred 137 * @return Whether the transfer was successful or not 138 */ 139 function transfer(address _to, uint256 _amount) external returns (bool success) { 140 require(transfersEnabled); 141 return doTransfer(msg.sender, _to, _amount); 142 } 143 144 /** 145 * @notice Send `_amount` tokens to `_to` from `_from` on the condition it 146 * is approved by `_from` 147 * @param _from The address holding the tokens being transferred 148 * @param _to The address of the recipient 149 * @param _amount The amount of tokens to be transferred 150 * @return True if the transfer was successful 151 */ 152 function transferFrom( 153 address _from, 154 address _to, 155 uint256 _amount 156 ) 157 external 158 returns (bool success) 159 { 160 161 // The controller of this contract can move tokens around at will, 162 // this is important to recognize! Confirm that you trust the 163 // controller of this contract, which in most situations should be 164 // another open source smart contract or 0x0 165 if (msg.sender != controller) { 166 require(transfersEnabled); 167 168 // The standard ERC 20 transferFrom functionality 169 if (allowed[_from][msg.sender] < _amount) { 170 return false; 171 } 172 allowed[_from][msg.sender] -= _amount; 173 } 174 return doTransfer(_from, _to, _amount); 175 } 176 177 /** 178 * @dev This is the actual transfer function in the token contract, it can 179 * only be called by other functions in this contract. 180 * @param _from The address holding the tokens being transferred 181 * @param _to The address of the recipient 182 * @param _amount The amount of tokens to be transferred 183 * @return True if the transfer was successful 184 */ 185 function doTransfer( 186 address _from, 187 address _to, 188 uint _amount 189 ) 190 internal 191 returns(bool) 192 { 193 194 if (_amount == 0) { 195 return true; 196 } 197 198 require(parentSnapShotBlock < block.number); 199 200 // Do not allow transfer to 0x0 or the token contract itself 201 require((_to != address(0)) && (_to != address(this))); 202 203 // If the amount being transfered is more than the balance of the 204 // account the transfer returns false 205 uint256 previousBalanceFrom = balanceOfAt(_from, block.number); 206 if (previousBalanceFrom < _amount) { 207 return false; 208 } 209 210 // Alerts the token controller of the transfer 211 if (isContract(controller)) { 212 require(TokenController(controller).onTransfer(_from, _to, _amount)); 213 } 214 215 // First update the balance array with the new value for the address 216 // sending the tokens 217 updateValueAtNow(balances[_from], previousBalanceFrom - _amount); 218 219 // Then update the balance array with the new value for the address 220 // receiving the tokens 221 uint256 previousBalanceTo = balanceOfAt(_to, block.number); 222 require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow 223 updateValueAtNow(balances[_to], previousBalanceTo + _amount); 224 225 // An event to make the transfer easy to find on the blockchain 226 emit Transfer(_from, _to, _amount); 227 228 return true; 229 } 230 231 function doApprove( 232 address _from, 233 address _spender, 234 uint256 _amount 235 ) 236 internal 237 returns (bool) 238 { 239 require(transfersEnabled); 240 241 // To change the approve amount you first have to reduce the addresses` 242 // allowance to zero by calling `approve(_spender,0)` if it is not 243 // already 0 to mitigate the race condition described here: 244 // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 245 require((_amount == 0) || (allowed[_from][_spender] == 0)); 246 247 // Alerts the token controller of the approve function call 248 if (isContract(controller)) { 249 require(TokenController(controller).onApprove(_from, _spender, _amount)); 250 } 251 252 allowed[_from][_spender] = _amount; 253 emit Approval(_from, _spender, _amount); 254 return true; 255 } 256 257 /** 258 * @param _owner The address that's balance is being requested 259 * @return The balance of `_owner` at the current block 260 */ 261 function balanceOf(address _owner) external view returns (uint256 balance) { 262 return balanceOfAt(_owner, block.number); 263 } 264 265 /** 266 * @notice `msg.sender` approves `_spender` to spend `_amount` tokens on 267 * its behalf. This is a modified version of the ERC20 approve function 268 * to be a little bit safer 269 * @param _spender The address of the account able to transfer the tokens 270 * @param _amount The amount of tokens to be approved for transfer 271 * @return True if the approval was successful 272 */ 273 function approve(address _spender, uint256 _amount) external returns (bool success) { 274 doApprove(msg.sender, _spender, _amount); 275 } 276 277 /** 278 * @dev This function makes it easy to read the `allowed[]` map 279 * @param _owner The address of the account that owns the token 280 * @param _spender The address of the account able to transfer the tokens 281 * @return Amount of remaining tokens of _owner that _spender is allowed 282 * to spend 283 */ 284 function allowance( 285 address _owner, 286 address _spender 287 ) 288 external 289 view 290 returns (uint256 remaining) 291 { 292 return allowed[_owner][_spender]; 293 } 294 /** 295 * @notice `msg.sender` approves `_spender` to send `_amount` tokens on 296 * its behalf, and then a function is triggered in the contract that is 297 * being approved, `_spender`. This allows users to use their tokens to 298 * interact with contracts in one function call instead of two 299 * @param _spender The address of the contract able to transfer the tokens 300 * @param _amount The amount of tokens to be approved for transfer 301 * @return True if the function call was successful 302 */ 303 function approveAndCall( 304 address _spender, 305 uint256 _amount, 306 bytes calldata _extraData 307 ) 308 external 309 returns (bool success) 310 { 311 require(doApprove(msg.sender, _spender, _amount)); 312 313 ApproveAndCallFallBack(_spender).receiveApproval( 314 msg.sender, 315 _amount, 316 address(this), 317 _extraData 318 ); 319 320 return true; 321 } 322 323 /** 324 * @dev This function makes it easy to get the total number of tokens 325 * @return The total number of tokens 326 */ 327 function totalSupply() external view returns (uint) { 328 return totalSupplyAt(block.number); 329 } 330 331 332 //////////////// 333 // Query balance and totalSupply in History 334 //////////////// 335 336 /** 337 * @dev Queries the balance of `_owner` at a specific `_blockNumber` 338 * @param _owner The address from which the balance will be retrieved 339 * @param _blockNumber The block number when the balance is queried 340 * @return The balance at `_blockNumber` 341 */ 342 function balanceOfAt( 343 address _owner, 344 uint _blockNumber 345 ) 346 public 347 view 348 returns (uint) 349 { 350 351 // These next few lines are used when the balance of the token is 352 // requested before a check point was ever created for this token, it 353 // requires that the `parentToken.balanceOfAt` be queried at the 354 // genesis block for that token as this contains initial balance of 355 // this token 356 if ((balances[_owner].length == 0) || (balances[_owner][0].fromBlock > _blockNumber)) { 357 if (address(parentToken) != address(0)) { 358 return parentToken.balanceOfAt(_owner, min(_blockNumber, parentSnapShotBlock)); 359 } else { 360 // Has no parent 361 return 0; 362 } 363 364 // This will return the expected balance during normal situations 365 } else { 366 return getValueAt(balances[_owner], _blockNumber); 367 } 368 } 369 370 /** 371 * @notice Total amount of tokens at a specific `_blockNumber`. 372 * @param _blockNumber The block number when the totalSupply is queried 373 * @return The total amount of tokens at `_blockNumber` 374 */ 375 function totalSupplyAt(uint _blockNumber) public view returns(uint) { 376 377 // These next few lines are used when the totalSupply of the token is 378 // requested before a check point was ever created for this token, it 379 // requires that the `parentToken.totalSupplyAt` be queried at the 380 // genesis block for this token as that contains totalSupply of this 381 // token at this block number. 382 if ((totalSupplyHistory.length == 0) || (totalSupplyHistory[0].fromBlock > _blockNumber)) { 383 if (address(parentToken) != address(0)) { 384 return parentToken.totalSupplyAt(min(_blockNumber, parentSnapShotBlock)); 385 } else { 386 return 0; 387 } 388 389 // This will return the expected totalSupply during normal situations 390 } else { 391 return getValueAt(totalSupplyHistory, _blockNumber); 392 } 393 } 394 395 //////////////// 396 // Clone Token Method 397 //////////////// 398 399 /** 400 * @notice Creates a new clone token with the initial distribution being 401 * this token at `snapshotBlock` 402 * @param _cloneTokenName Name of the clone token 403 * @param _cloneDecimalUnits Number of decimals of the smallest unit 404 * @param _cloneTokenSymbol Symbol of the clone token 405 * @param _snapshotBlock Block when the distribution of the parent token is 406 * copied to set the initial distribution of the new clone token; 407 * if the block is zero than the actual block, the current block is used 408 * @param _transfersEnabled True if transfers are allowed in the clone 409 * @return The address of the new MiniMeToken Contract 410 */ 411 function createCloneToken( 412 string calldata _cloneTokenName, 413 uint8 _cloneDecimalUnits, 414 string calldata _cloneTokenSymbol, 415 uint _snapshotBlock, 416 bool _transfersEnabled 417 ) 418 external 419 returns(address) 420 { 421 uint snapshotBlock = _snapshotBlock; 422 if (snapshotBlock == 0) { 423 snapshotBlock = block.number; 424 } 425 MiniMeToken cloneToken = MiniMeToken( 426 tokenFactory.createCloneToken( 427 address(this), 428 snapshotBlock, 429 _cloneTokenName, 430 _cloneDecimalUnits, 431 _cloneTokenSymbol, 432 _transfersEnabled 433 )); 434 435 cloneToken.changeController(msg.sender); 436 437 // An event to make the token easy to find on the blockchain 438 emit NewCloneToken(address(cloneToken), snapshotBlock); 439 return address(cloneToken); 440 } 441 442 //////////////// 443 // Generate and destroy tokens 444 //////////////// 445 446 /** 447 * @notice Generates `_amount` tokens that are assigned to `_owner` 448 * @param _owner The address that will be assigned the new tokens 449 * @param _amount The quantity of tokens generated 450 * @return True if the tokens are generated correctly 451 */ 452 function generateTokens( 453 address _owner, 454 uint _amount 455 ) 456 external 457 onlyController 458 returns (bool) 459 { 460 uint curTotalSupply = totalSupplyAt(block.number); 461 require(curTotalSupply + _amount >= curTotalSupply); // Check for overflow 462 uint previousBalanceTo = balanceOfAt(_owner, block.number); 463 require(previousBalanceTo + _amount >= previousBalanceTo); // Check for overflow 464 updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount); 465 updateValueAtNow(balances[_owner], previousBalanceTo + _amount); 466 emit Transfer(address(0), _owner, _amount); 467 return true; 468 } 469 470 /** 471 * @notice Burns `_amount` tokens from `_owner` 472 * @param _owner The address that will lose the tokens 473 * @param _amount The quantity of tokens to burn 474 * @return True if the tokens are burned correctly 475 */ 476 function destroyTokens( 477 address _owner, 478 uint _amount 479 ) 480 external 481 onlyController 482 returns (bool) 483 { 484 uint curTotalSupply = totalSupplyAt(block.number); 485 require(curTotalSupply >= _amount); 486 uint previousBalanceFrom = balanceOfAt(_owner, block.number); 487 require(previousBalanceFrom >= _amount); 488 updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount); 489 updateValueAtNow(balances[_owner], previousBalanceFrom - _amount); 490 emit Transfer(_owner, address(0), _amount); 491 return true; 492 } 493 494 //////////////// 495 // Enable tokens transfers 496 //////////////// 497 498 /** 499 * @notice Enables token holders to transfer their tokens freely if true 500 * @param _transfersEnabled True if transfers are allowed in the clone 501 */ 502 function enableTransfers(bool _transfersEnabled) external onlyController { 503 transfersEnabled = _transfersEnabled; 504 } 505 506 //////////////// 507 // Internal helper functions to query and set a value in a snapshot array 508 //////////////// 509 510 /** 511 * @dev `getValueAt` retrieves the number of tokens at a given block number 512 * @param checkpoints The history of values being queried 513 * @param _block The block number to retrieve the value at 514 * @return The number of tokens being queried 515 */ 516 function getValueAt( 517 Checkpoint[] storage checkpoints, 518 uint _block 519 ) 520 internal 521 view 522 returns (uint) 523 { 524 if (checkpoints.length == 0) { 525 return 0; 526 } 527 528 // Shortcut for the actual value 529 if (_block >= checkpoints[checkpoints.length-1].fromBlock) { 530 return checkpoints[checkpoints.length-1].value; 531 } 532 if (_block < checkpoints[0].fromBlock) { 533 return 0; 534 } 535 536 // Binary search of the value in the array 537 uint min = 0; 538 uint max = checkpoints.length-1; 539 while (max > min) { 540 uint mid = (max + min + 1) / 2; 541 if (checkpoints[mid].fromBlock<=_block) { 542 min = mid; 543 } else { 544 max = mid-1; 545 } 546 } 547 return checkpoints[min].value; 548 } 549 550 /** 551 * @dev `updateValueAtNow` used to update the `balances` map and the 552 * `totalSupplyHistory` 553 * @param checkpoints The history of data being updated 554 * @param _value The new number of tokens 555 */ 556 function updateValueAtNow(Checkpoint[] storage checkpoints, uint _value) internal { 557 if ((checkpoints.length == 0) || (checkpoints[checkpoints.length - 1].fromBlock < block.number)) { 558 Checkpoint storage newCheckPoint = checkpoints[checkpoints.length++]; 559 newCheckPoint.fromBlock = uint128(block.number); 560 newCheckPoint.value = uint128(_value); 561 } else { 562 Checkpoint storage oldCheckPoint = checkpoints[checkpoints.length-1]; 563 oldCheckPoint.value = uint128(_value); 564 } 565 } 566 567 /** 568 * @dev Internal function to determine if an address is a contract 569 * @param _addr The address being queried 570 * @return True if `_addr` is a contract 571 */ 572 function isContract(address _addr) internal returns(bool) { 573 uint size; 574 if (_addr == address(0)) { 575 return false; 576 } 577 assembly { 578 size := extcodesize(_addr) 579 } 580 return size>0; 581 } 582 583 /** 584 * @dev Helper function to return a min betwen the two uints 585 */ 586 function min(uint a, uint b) internal pure returns (uint) { 587 return a < b ? a : b; 588 } 589 590 /** 591 * @notice The fallback function: If the contract's controller has not been 592 * set to 0, then the `proxyPayment` method is called which relays the 593 * ether and creates tokens as described in the token controller contract 594 */ 595 function () external payable { 596 require(isContract(controller)); 597 require(TokenController(controller).proxyPayment.value(msg.value)(msg.sender)); 598 } 599 600 ////////// 601 // Safety Methods 602 ////////// 603 604 /** 605 * @notice This method can be used by the controller to extract mistakenly 606 * sent tokens to this contract. 607 * @param _token The address of the token contract that you want to recover 608 * set to 0 in case you want to extract ether. 609 */ 610 function claimTokens(address _token) external onlyController { 611 if (_token == address(0)) { 612 controller.transfer(address(this).balance); 613 return; 614 } 615 616 MiniMeToken token = MiniMeToken(address(uint160(_token))); 617 uint balance = token.balanceOf(address(this)); 618 token.transfer(controller, balance); 619 emit ClaimedTokens(_token, controller, balance); 620 } 621 622 //////////////// 623 // Events 624 //////////////// 625 event ClaimedTokens(address indexed _token, address indexed _controller, uint _amount); 626 event Transfer(address indexed _from, address indexed _to, uint256 _amount); 627 event NewCloneToken(address indexed _cloneToken, uint snapshotBlock); 628 event Approval( 629 address indexed _owner, 630 address indexed _spender, 631 uint256 _amount 632 ); 633 634 }