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;
  }

}

 

转载于:https://my.oschina.net/gavinzheng731/blog/1821804

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值