Netkiller Blockchain 手札
作者正在找工作,聯繫方式 13113668890
Mr. Neo Chan, 陳景峯(BG7NYT)
中國廣東省深圳市望海路半島城邦三期
518067
+86 13113668890
<[email protected]>
文檔始創於2018-02-10
版權 © 2018 Netkiller(Neo Chan). All rights reserved.
版權聲明
轉載請與作者聯繫,轉載時請務必標明文章原始出處和作者信息及本聲明。
|
|
|
|
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 HTTP2 + Oauth2 + Jwt 接口認證實例
Android VideoView 視頻播放完成例子(進度條,播放時間,暫停,拖動)