Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^0.4.19;
- /**
- * @title safemath
- * @dev Math operations with safety checks that throw on error
- */
- library safemath {
- /**
- * @dev Multiplies two numbers, throws on overflow.
- */
- function mul(uint256 a, uint256 b) internal pure returns (uint256) {
- if (a == 0) {
- return 0;
- }
- uint256 c = a * b;
- assert(c / a == b);
- return c;
- }
- /**
- * @dev Integer division of two numbers, truncating the quotient.
- */
- function div(uint256 a, uint256 b) internal pure returns (uint256) {
- // assert(b > 0); // Solidity automatically throws when dividing by 0
- uint256 c = a / b;
- // assert(a == b * c + a % b); // There is no case in which this doesn't hold
- return c;
- }
- /**
- * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
- */
- function sub(uint256 a, uint256 b) internal pure returns (uint256) {
- assert(b <= a);
- return a - b;
- }
- /**
- * @dev Adds two numbers, throws on overflow.
- */
- function add(uint256 a, uint256 b) internal pure returns (uint256) {
- uint256 c = a + b;
- assert(c >= a);
- return c;
- }
- }
- /**
- * @title ownable
- * @dev The ownable contract has an owner address, and provides basic authorization control
- * functions, this simplifies the implementation of "user permissions".
- */
- contract ownable {
- address public owner;
- event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
- /**
- * @dev The Ownable constructor sets the original `owner` of the contract to the sender
- * account.
- */
- constructor () public {
- owner = msg.sender;
- }
- /**
- * @dev Throws if called by any account other than the owner.
- */
- modifier onlyOwner() {
- require(msg.sender == owner);
- _;
- }
- /**
- * @dev Allows the current owner to transfer control of the contract to a newOwner.
- * @param newOwner The address to transfer ownership to.
- */
- function transferOwnership(address newOwner) public onlyOwner {
- require(newOwner != address(0));
- emit OwnershipTransferred(owner, newOwner);
- owner = newOwner;
- }
- }
- contract erc721 {
- event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
- event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
- function balanceOf(address _owner) public view returns (uint256 _balance);
- function ownerOf(uint256 _tokenId) public view returns (address _owner);
- function transfer(address _to, uint256 _tokenId) public;
- function approve(address _to, uint256 _tokenId) public;
- function takeOwnership(uint256 _tokenId) public;
- }
- /**
- * @title KTaccess
- * @author Yihan -- CyberMiles
- * @dev This contract is for regulating the owners' addr.
- * Inherited by KTfactory.
- */
- contract KTaccess is ownable{
- address public o1Address;
- address public o2Address;
- address public o3Address;
- modifier onlyOLevel() {
- require(
- msg.sender == o1Address ||
- msg.sender == o2Address ||
- msg.sender == o3Address ||
- msg.sender == owner
- );
- _;
- }
- function setO1(address _newAddr) external onlyOLevel {
- require(_newAddr != address(0));
- o1Address = _newAddr;
- }
- function setO2(address _newAddr) external onlyOLevel {
- require(_newAddr != address(0));
- o2Address = _newAddr;
- }
- function setO3(address _newAddr) external onlyOLevel {
- require(_newAddr != address(0));
- o3Address = _newAddr;
- }
- }
- /**
- * @title KTfactory
- * @author Yihan -- CyberMiles
- * @dev This main contract for creating KTs.
- *
- * A KT, which is the token issued by Krypital, has the following properties:
- * an officail note that can be created only by the contract owner;
- * a personal note that can be modified by the current owner of the token;
- * a bool value indicating if the token is currently frozen by Krypital;
- * a gene which is a hashed value that changes when mutate (merge or decompose). This is for some future interesting apps :D
- * level, namely, the level of the token. Apparently higher is better :D
- * id, the key used to map to the associated KT.
- *
- */
- contract KTfactory is ownable, KTaccess {
- using safemath for uint256;
- uint256 public maxId;
- uint256 public initial_supply;
- uint256 public curr_number;
- event NewKT(string note, uint256 gene, uint256 level, uint256 tokenId);
- event UpdateNote(string newNote, uint256 tokenId);
- event PauseToken(uint256 tokenId);
- event UnpauseToken(uint256 tokenId);
- struct KT {
- string officialNote;
- string personalNote;
- bool paused;
- uint256 gene;
- uint256 level;
- uint256 id;
- }
- mapping (uint256 => KT) public KTs;
- mapping (uint => address) public KTToOwner;
- mapping (address => uint) ownerKTCount;
- modifier onlyOwnerOf(uint token_id) {
- require(msg.sender == KTToOwner[token_id]);
- _;
- }
- modifier whenNotFrozen(uint token_id) {
- require(KTs[token_id].paused == false);
- _;
- }
- modifier withinTotal() {
- require(curr_number<= initial_supply);
- _;
- }
- modifier hasKT(uint token_id) {
- require(KTs[token_id].id != 0);
- _;
- }
- /**
- * @dev The constructor. Sets the initial supply and some other global variables.
- * That's right, Krypital will only issue 2100 tokens in total. It also means the total number of KTs will not exceed this number!
- */
- constructor() public {
- initial_supply = 2100;
- maxId=0;
- curr_number=0;
- }
- /**
- * @dev The creator of KTs. Only done by Krypital.
- * @param oNote - the official, special note left only by Krypital!
- */
- function _createKT(string oNote) public onlyOLevel withinTotal {
- uint thisId = maxId + 1;
- string pNote;
- uint256 thisGene = uint256(keccak256(oNote));
- KT memory thisKT = KT({
- officialNote: oNote,
- personalNote: pNote,
- paused: false,
- gene: thisGene,
- level: 1,
- id: thisId
- });
- KTs[thisId] = thisKT;
- maxId = maxId + 1;
- curr_number = curr_number + 1;
- KTToOwner[thisId] = msg.sender;
- ownerKTCount[msg.sender]++;
- emit NewKT(oNote, thisGene, 1, thisId);
- }
- /**
- * @dev This method is for editing your personal note!
- * @param note - the note you want the old one to be replaced by
- * @param token_id - just token id
- */
- function _editPersonalNote(string note, uint token_id) public onlyOwnerOf(token_id) hasKT(token_id){
- KT storage currKT = KTs[token_id];
- currKT.personalNote = note;
- emit UpdateNote(note, token_id);
- }
- /**
- * @dev Pauses a token, done by Krypital
- * When a token is paused by Krypital, the owner of the token can still update the personal note but the ownership cannot be transferred.
- * @param token_id - just token id
- */
- function pauseToken(uint token_id) public onlyOLevel hasKT(token_id){
- KT storage currKT = KTs[token_id];
- currKT.paused = true;
- emit PauseToken(token_id);
- }
- /**
- * @dev Unpauses a token, done by Krypital
- * @param token_id - just token id
- */
- function unpauseToken(uint token_id) public onlyOLevel hasKT(token_id){
- KT storage currKT = KTs[token_id];
- currKT.paused = false;
- emit UnpauseToken(token_id);
- }
- }
- /**
- * @title KT
- * @author Yihan -- CyberMiles
- * @dev This contract is the contract regulating the transfer, decomposition, merging mechanism amaong the tokens.
- */
- contract KT is KTfactory, erc721 {
- using safemath for uint256;
- mapping (uint => address) KTApprovals;
- /**
- * @dev The modifer to regulate a KT's decomposability.
- * A level 1 KT is not decomposable.
- * @param token_id - simply token id.
- */
- modifier decomposeAllowed(uint token_id){
- require(KTs[token_id].level > 1);
- _;
- }
- event Decompose(uint256 tokenId);
- event Merge(uint256 tokenId1, uint256 tokenId2);
- /**
- * @dev This is for getting the ether back to the contract owner's account. Just in case someone generous sends the creator some ethers :P
- */
- function withdraw() external onlyOwner {
- owner.transfer(this.balance);
- }
- /**
- * @dev For checking how many tokens you own.
- * @param _owner - the owner's addr
- */
- function balanceOf(address _owner) public view returns(uint256) {
- return ownerKTCount[_owner];
- }
- /**
- * @dev For checking the owner of the given token.
- * @param _tokenId - just token id
- */
- function ownerOf(uint256 _tokenId) public view returns(address) {
- return KTToOwner[_tokenId];
- }
- /**
- * @dev the private helper function for transfering ownership.
- * @param _from - current KT owner
- * @param _to - new KT owner
- * @param _tokenId - just token id
- */
- function _transfer(address _from, address _to, uint256 _tokenId) private hasKT(_tokenId) {
- ownerKTCount[_to] = ownerKTCount[_to].add(1);
- ownerKTCount[msg.sender] = ownerKTCount[msg.sender].sub(1);
- KTToOwner[_tokenId] = _to;
- emit Transfer(_from, _to, _tokenId);
- }
- /**
- * @dev This method can be called if you are the token owner and you want to transfer the token to someone else.
- * @param _to - new KT owner
- * @param _tokenId - just token id
- */
- function transfer(address _to, uint256 _tokenId) public whenNotFrozen(_tokenId) onlyOwnerOf(_tokenId) hasKT(_tokenId){
- require(_to != address(0));
- _transfer(msg.sender, _to, _tokenId);
- }
- /**
- * @dev An approved user can 'claim' a token of another user.
- * @param _to - new KT owner
- * @param _tokenId - just token id
- */
- function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) hasKT(_tokenId) {
- require(_to != address(0));
- KTApprovals[_tokenId] = _to;
- emit Approval(msg.sender, _to, _tokenId);
- }
- /**
- * @dev The user to be approved must be approved by the current token holder.
- * @param _tokenId - just token id
- */
- function takeOwnership(uint256 _tokenId) public whenNotFrozen(_tokenId) hasKT(_tokenId){
- require(KTApprovals[_tokenId] == msg.sender);
- address owner = ownerOf(_tokenId);
- _transfer(owner, msg.sender, _tokenId);
- }
- /**
- * @dev This method is for decomposing (or split) a token. Only can be done by token holder when token is not frozen.
- * Note: one of the tokens will take the original token's place, that is, the old ID will actually map to a new token!
- * Level down by 1!!! A level 1 token cannot be decomposed.
- * The genes of the two new born tokens will be both identical to the old token.
- * Notes of the two new tokens are identical to the original token.
- */
- function decompose(uint256 token_id) public whenNotFrozen(token_id) onlyOwnerOf(token_id) decomposeAllowed(token_id) hasKT(token_id) withinTotal{
- KT storage decomposed = KTs[token_id];
- decomposed.level = decomposed.level-1;
- decomposed.gene = decomposed.gene/2;
- KT memory newKT = KT({
- officialNote: decomposed.officialNote,
- personalNote: decomposed.personalNote,
- paused: false,
- gene: decomposed.gene,
- level: decomposed.level,
- id: maxId.add(1)
- });
- maxId=maxId.add(1);
- curr_number=curr_number.add(1);
- KTs[maxId]=newKT;
- KTToOwner[maxId]=KTToOwner[token_id];
- ownerKTCount[msg.sender]=ownerKTCount[msg.sender].add(1);
- emit Decompose(token_id);
- }
- /**
- * @dev This function is for merging 2 tokens. Only tokens with the same levels can be merge. A user can only choose to merge from his own tokens.
- * After merging, id and official note are merged to the previous token passed in the args.
- * NOTE that the notes associated with the second token will be wiped out! Use with your caution.
- * Level up by 1!!!
- * New gene = (gene1 + gene2) / 2
- * @param id1 - the ID to the 1st token, this ID will remain after merging.
- * @param id2 - the ID of the 2nd token, this ID will map to nothing after merging!!
- */
- function merge(uint256 id1, uint256 id2) public hasKT(id1) hasKT(id2) whenNotFrozen(id1) whenNotFrozen(id2) onlyOwnerOf(id1) onlyOwnerOf(id2){
- require(KTs[id1].level == KTs[id2].level);
- KT storage token1 = KTs[id1];
- token1.gene = (token1.gene + KTs[id2].gene) / 2;
- token1.level = (token1.level).add(1);
- KT memory toDelete = KT ({
- officialNote: "",
- personalNote: "",
- paused: false,
- gene: 0,
- level: 0,
- id: 0
- });
- KTs[id2] = toDelete;
- curr_number = curr_number.sub(1);
- KTToOwner[id2] = address(0);
- ownerKTCount[msg.sender] = ownerKTCount[msg.sender].sub(1);
- emit Merge(id1, id2);
- }
- }
Add Comment
Please, Sign In to add comment