藝術品區塊鏈溯源防僞平臺(連載二)數字資產的投資與數字資產的份額化 原

Netkiller Blockchain 手札

作者正在找工作,聯繫方式 13113668890

Mr. Neo Chan, 陳景峯(BG7NYT)



中國廣東省深圳市望海路半島城邦三期
518067
+86 13113668890

<[email protected]>

文檔始創於2018-02-10

版權 © 2018 Netkiller(Neo Chan). All rights reserved.

 

版權聲明

轉載請與作者聯繫,轉載時請務必標明文章原始出處和作者信息及本聲明。

http://www.netkiller.cn
http://netkiller.github.io
http://netkiller.sourceforge.net
微信訂閱號 netkiller-ebook (微信掃描二維碼)
QQ:13721218 請註明“讀者”
QQ羣:128659835 請註明“讀者”

2.10.5. 資產投資與份額持有

傳統藝術品投資門檻非常高,一是用戶不知道從哪些渠道可以投資,二是藝術品價值過高,三是藝術品簡單難。這導致了投資藝術品門檻過高。 Token 能實現份額化,實現人人蔘與,人人持有,P2P交易。

例如某機構上鍊一件藝術品,用戶可以投資該藝術品的一定份額,可以轉讓他持有的權益。且交易去中心化,不受任何機構,管理者的制約。

下面的合約可以展示如何分割藝術品份額,最終達到鏈上資產的份額分割和持有與交易。

pragma solidity ^0.4.25;

/**
 * @title SafeMath
 * @dev Math operations with safety checks that revert on error
 */
library SafeMath {

  /**
  * @dev Multiplies two numbers, reverts on overflow.
  */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
    // benefit is lost if 'b' is also tested.
    // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
    if (a == 0) {
      return 0;
    }

    uint256 c = a * b;
    require(c / a == b);

    return c;
  }

  /**
  * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
  */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b > 0); // Solidity only automatically asserts 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, reverts on overflow (i.e. if subtrahend is greater than minuend).
  */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a);
    uint256 c = a - b;

    return c;
  }

  /**
  * @dev Adds two numbers, reverts on overflow.
  */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a);

    return c;
  }

  /**
  * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
  * reverts when dividing by zero.
  */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0);
    return a % b;
  }
}        

contract Ownable {
    
    address public owner;
    
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
    
    constructor() public {
        owner = msg.sender;
    }
    
    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    
    function transferOwnership(address newOwner) public onlyOwner {
        require(newOwner != address(0));
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

}

contract NetkillerAssetsToken is Ownable {
    using SafeMath for uint256;
    
    string public name;
    string public symbol;
    uint public decimals;
    uint256 public totalSupply;
    
    mapping(address => mapping(string => uint256)) internal balances;
    mapping(string => address) internal tokens;
    
    event Transfer(address indexed _from, address indexed _to, string indexed _tokenId);
    event Burn(address indexed from, string _tokenId);
    
    constructor(
        string tokenName,
        string tokenSymbol,
        uint decimalUnits
    ) public {
        owner = msg.sender;
        name = tokenName;
        symbol = tokenSymbol; 
        decimals = decimalUnits;
        totalSupply = 0; 
    }
    
    function add(address _owner, string _tokenId) onlyOwner returns(bool status){
        balances[_owner][_tokenId] = 100 * 10 ** uint256(decimals);
        tokens[_tokenId] = _owner;
        totalSupply = totalSupply.add(1);
        return true;
    }
    
    function balanceOf(address _owner, string _tokenId) constant returns(uint balance){ 
        return balances[_owner][_tokenId];
    }

    function ownerOf(string _tokenId) constant returns (address owner) {
        return tokens[_tokenId];
    }
    
    function transfer(address _to, string _tokenId){
        
        address _from = msg.sender;
        uint256 amount = balances[_from][_tokenId];
        transfer(_to, amount, _tokenId);
    }
    function transfer(address _to, uint256 _value, string _tokenId){
        require(msg.sender == ownerOf(_tokenId));
        require(msg.sender != _to);
        require(_to != address(0));
        
        address _from = msg.sender;
        uint256 amount = balances[_from][_tokenId];
        require(amount >= _value);
        
        balances[_from][_tokenId] = balances[_from][_tokenId].sub(_value);
        balances[_to][_tokenId] = balances[_to][_tokenId].add(_value);
        tokens[_tokenId] = _to;

        emit Transfer(_from, _to, _tokenId);
    }
    
    function burn(address _owner, string _tokenId) onlyOwner public returns (bool success) {
        require(balances[_owner][_tokenId] > 0 && balances[_owner][_tokenId] == 100 * 10 ** uint256(decimals));

        balances[_owner][_tokenId] = 0;
        tokens[_tokenId] = address(0);

        totalSupply = totalSupply.sub(1);
        emit Burn(msg.sender, _tokenId);
        return true;
    }
    
}

由於 ERC721 不太符合我的需求,所以我結合 ERC20 和 ERC721 寫出了我的合約。合約儘量保持了ERC20的使用習慣,函數定義儘量兼容 ERC20。

我們來看下面的構造方法,每個種類的物品一個合約,例如字畫,陶瓷,青銅器。

constructor(
        string tokenName,
        string tokenSymbol,
        uint decimalUnits
    ) public {
        owner = msg.sender;
        name = tokenName;
        symbol = tokenSymbol; 
        decimals = decimalUnits;
        totalSupply = 0; 
    }

通過下面函數,添加資產到 Token,使鏈上資產與Token綁定。

function add(address _owner, string _tokenId) onlyOwner returns(bool status){
        balances[_owner][_tokenId] = 100 * 10 ** uint256(decimals);
        tokens[_tokenId] = _owner;
        totalSupply = totalSupply.add(1);
        return true;
    }

balances[_owner][_tokenId] = 100 * 10 ** uint256(decimals); 初始化份額是 100 表示 100%

totalSupply = totalSupply.add(1); 物品件數加一。可以用於統計鏈上資產的數量。

下面函數是查詢資產的持有人

function ownerOf(string _tokenId) constant returns (address owner) {
        return tokens[_tokenId];
    }

下面函數是,權益轉讓和權益份額轉讓。

function transfer(address _to, string _tokenId){
        
        address _from = msg.sender;
        uint256 amount = balances[_from][_tokenId];
        transfer(_to, amount, _tokenId);
    }
    function transfer(address _to, uint256 _value, string _tokenId){
        require(msg.sender == ownerOf(_tokenId));
        require(msg.sender != _to);
        require(_to != address(0));
        
        address _from = msg.sender;
        uint256 amount = balances[_from][_tokenId];
        require(amount >= _value);
        
        balances[_from][_tokenId] = balances[_from][_tokenId].sub(_value);
        balances[_to][_tokenId] = balances[_to][_tokenId].add(_value);
        tokens[_tokenId] = _to;

        emit Transfer(_from, _to, _tokenId);
    }

接下來,我們就是可以開發 Dapp 錢包了,在錢包中實現資產的轉移交易。

這個合約可以一直到 EOS 上,Hyperledger Fabric 不可以,因爲 Fabric 沒有鎖的機制,會導致計算出錯。

作者的相關文章:

藝術品區塊鏈溯源防僞平臺(連載一)

Android 相機 LED 做手電筒

Android EventBus

Android 相機與相冊開發

Android i18n 國際化

Android HTTP2 + Oauth2 + Jwt 接口認證實例

Android VideoView 視頻播放完成例子(進度條,播放時間,暫停,拖動)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章