ERC998 原

ERC998是可拆解(Composable)的ERC721

父幣指的是ERC-998 token, 子幣指的是 父幣所擁有的ERC-721 或者 ERC-20 tokens .

/// tokenId of composable, mapped to child contract address
/// child contract address mapped to child tokenId or amount
mapping(uint256 => mapping(address => uint256)) children;

ERC998合約的mapping是由父幣的TokenID映射到一個子幣的mapping:子幣的合約地址到子幣TokenID的映射。

    如果子幣是ERC721, mapping是子幣的合約地址到子幣TokenID的映射。

    如果子幣是ERC20, mapping是子幣的合約地址到子幣TokenID的數量

 

增加子幣

/// add ERC-721 children by tokenId
/// @requires owner to approve transfer from this contract
/// call _childContract.approve(this, _childTokenId)
/// where this is the address of the parent token contract
addChild(
  uint256 _tokenId,
  address _childContract,
  uint256 _childTokenId
) {
  // call the transfer function of the child contract
  // if approve was called with the address of this contract
  // the ownership of the child token(s) will be transferred to this contract
  require(
    _childContract.call(
      bytes4(sha3("transferFrom(address,address,uint256)")),
      msg.sender, this, _childTokenId
    )
  );
  // if successful, add children to the mapping
  // generate a 'pseudo address' for the specific child tokenId
  // address construction is analogous to 'contract address + nonce'
  // use 0 == no child token, and 1 == child token exists
  address childToken = address(
    keccak256(_childContract, _childTokenId)
  );
  children[_tokenId][childToken] = 1;
}

/// add ERC-20 children by amount
/// @requires owner to approve transfer from this contract
/// call _childContract.approve(this, _amount)
addChildAmount(
  uint256 _tokenId,
  address _childContract,
  uint256 _amount
) {
  // call the transfer function of the child contract
  // if approve was called with the address of this contract
  // the ownership of the child token(s) will be transferred to this contract
  require(
    _childContract.call(
      bytes4(sha3("transferFrom(address,address,uint256)")),
      msg.sender, this, _amount
    )
  );
  // if successful, add children to the mapping
  children[_tokenId][_childContract] += _amount;
}

條件:

  • 函數調用的發送者擁有父幣, the ERC-721規範定義並實現了一個標準方法_owns(address, tokenId)
  • 通過子幣合約地址,將父幣token ID映射到子幣token ID, 強制通過Bookkeeping映射保持父子關係

轉賬NFT - ERC721子幣

/// transfer ERC-721 child by _childTokenId
transferChild(
  address _to,
  uint256 _tokenId,
  address _childContract,
  uint256 _childTokenId
) {
  // require ownership of parent token &&
  // check parent token owns the child token
  // use the 'pseudo address' for the specific child tokenId
  address childToken = address(
    keccak256(_childContract, _childTokenId)
  );
  require(_owns(msg.sender, _tokenId));
  require(children[_tokenId][childToken] == 1);
  require(
    _childContract.call(
      // if true, transfer the child token
      bytes4(sha3("transfer(address,uint256)")), _to, _childTokenId
    )
  );
  // remove the parent token's ownership of the child token
  children[_tokenId][childToken] = 0;
}

條件:

  • 函數調用的發送者擁有父幣
  • 父幣有足夠的ERC20的賬戶餘額

 

轉賬FT - ERC20子幣

/// transfer ERC-20 child by _amount
transferChildAmount(
  address _to,
  uint256 _tokenId,
  address _childContract,
  uint256 _amount
) {
  // require ownership of parent token &&
  // check parent token owns enough balance of the child tokens
  require(_owns(msg.sender, _tokenId));
  require(children[_tokenId][_childContract] >= _amount);
  require(
    _childContract.call(
      // if true, transfer the child tokens
      // not a delegate call, the child tokens are owned by this contract
      bytes4(sha3("transfer(address,uint256)")),
      _to, _amount
    )
  );
  //decrement the parent token's balance of child tokens by _amount
  children[_tokenId][_childContract] -= _amount;
}

條件:

  • 函數調用的發送者擁有父幣
  • 父幣有足夠的ERC20的賬戶餘額

 ERC-998 Composable Non-Fungible Token Standard

參考

https://github.com/ethereum/EIPs

https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md

Crypto Disposable

 

源代碼 - https://ethfiddle.com/InrBR4V-KL 

//Write your own contracts here. Currently compiles using solc v0.4.15+commit.bbb8e64f.
pragma solidity ^0.4.18;

contract ERC721 {
  function ownerOf(uint256) public returns (address);
}

contract ComposableAssetFactory {  
  
  // which asset owns which other assets at which address
  mapping(uint256 => mapping(address => uint256)) children;

  // which address owns which tokens
  mapping(uint256 => address) owners;
  
  modifier onlyOwner(uint256 _tokenID) {
    require(msg.sender == owners[_tokenID]);
    _;
  }
  function registerOwner(uint256 _tokenID, address _contract) public returns (bool) {
    require(owners[_tokenID] == address(0));

    ERC721 erc721 = ERC721(_contract);

    address owner = erc721.ownerOf(_tokenID);
    assert(owner == msg.sender);

    owners[_tokenID] = msg.sender;
    return true;
  }
  // change owner of a token
  function changeOwner(address _newOwner, uint256 _tokenID) onlyOwner(_tokenID) public returns (bool) {
    owners[_tokenID] = _newOwner;
    return true;
  }
  
  // add erc20 child to a composable asset
  function addFungibleChild(uint256 _tokenID, address _childContract, uint256 _amount) onlyOwner(_tokenID) public returns (bool) {
    require(
      _childContract.call(
        bytes4(keccak256("transferFrom(address,address,uint256")),
        msg.sender,
        this,
        _amount
      )
    );

    // set as child
    children[_tokenID][_childContract] += _amount;
    return true;
  }

  // add erc721 child to a composable asset
  function addNonFungibleChild(uint256 _tokenID, address _childContract, uint256 _index) onlyOwner(_tokenID) public returns (bool) {
    require(
      _childContract.call(
        bytes4(keccak256("transferFrom(address,address,uint256")),
        msg.sender,
        this,
        _index
      )
    );

    // set as child
    children[_tokenID][_childContract] = _index;
    return true;
  }

  function transferNonFungibleChild(
    address _to,
    uint256 _tokenID,
    address _childContract,
    uint256 _childTokenID
  ) public onlyOwner(_tokenID) returns (bool) {
    require(children[_tokenID][_childContract] == _childTokenID);
    require(
      _childContract.call(
        bytes4(keccak256("transfer(address,uint256)")),
        _to, _childTokenID
      )
    );

    children[_tokenID][_childContract] = 0;
    return true;
  }

  function transferFungibleChild(
    address _to,
    uint256 _tokenID,
    address _childContract,
    uint256 _amount
  ) onlyOwner(_tokenID) public {
    require(children[_tokenID][_childContract] >= _amount);
    require(
      _childContract.call(
        bytes4(keccak256("transfer(address,uint256)")),
        _to, _amount
      )
    );

    children[_tokenID][_childContract] -= _amount;
  }

}

 

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