2

Use Case

I have a number of real-world objects that are stored in a central location. The deed to that object can be bought and sold without the actual object going anywhere. Deeds can be sold for tokens or redeemed for the physical object and tokens can be redeemed for cash or used to buy deeds to other objects.

Question

I'm in the very early stages of proposing a new dapp to my employer. I understand the concepts behind dapps and the Ethereum blockchain, but haven't done a deep dive into Solidity and the implementation details just yet. What I'm trying to determine is if Ethereum smart contracts can track the ownership of a particular real world object. All of the examples I have found so far demonstrate how to create a custom currency so the contract is really just adjusting numeric balances, not transferring ownership of a discrete object. I know the Ethereum blockchain can handle payments for these deeds using an ERC20 token, but can it be used to also track ownership of each deed or does that have to happen off-chain?

Update

I spent today looking at samples and experimenting on Remix and started moving in the following direction. FYI, I just started learning Solidity today, so be kind if I'm doing something completely wrong.

pragma solidity ^0.4.0;

/*************************
 * Managed abstract contract
 *************************/
contract Managed
{
    address internal _manager;

    function isManager(address addr) internal view returns (bool yes)
    {
        return addr == _manager;
    }
}

/*************************
 * MyToken concrete contract
 *************************/
contract MyToken is Managed
{
    string private _name;
    string private _symbol;
    uint8 private _decimals = 18;
    uint256 _totalSupply;

    mapping (address => uint256) private _balances;

    function MyToken(string name, string symbol, uint256 initialSupply) public 
    {
        _manager = msg.sender;
        _name = name;
        _symbol = symbol;
        _totalSupply = initialSupply * 10 ** uint256(_decimals);
        _balances[_manager] = _totalSupply;
    }

    function _getBalance(address from) private view returns (uint256 balance)
    {
        return _balances[from];
    }

    function getBalance() public view returns (uint256 balance)
    {
        return _getBalance(msg.sender);
    }

    event Transfer(address indexed from, address indexed to, uint256 amount);

    function _transfer(address from, address to, uint256 amount) private
    {
        _remove(from, amount);
        _add(to, amount);
    }

    function transfer(address to, uint256 amount) public 
    {
        _transfer(msg.sender, to, amount);
    }

    event Add(address indexed to, uint256 amount);

    function _add(address to, uint256 amount) private
    {
        require(to != 0x0);
        require(amount >= 0);
        require(_balances[to] + amount >= _balances[to]);

        _balances[to] += amount;
        _totalSupply += amount;

        Add(to, amount);
    }

    function add(address to, uint256 amount) public
    {
        require(isManager(msg.sender));
        _add(to, amount);
    }

    function add(uint256 amount) public
    {
        _add(msg.sender, amount);
    }

    event Remove(address indexed from, uint256 amount);

    function _remove(address from, uint256 amount) private
    {
        require(from != 0x0);
        require(amount >= 0);
        require(amount <= _balances[from]);

        _balances[from] -= amount;
        _totalSupply -= amount;

        Remove(from, amount);
    }

    function remove(address from, uint256 amount) public
    {
        require(isManager(msg.sender));
        _remove(from, amount);
    }

    function remove(uint256 amount) public
    {
        _remove(msg.sender, amount);
    }
}

/*************************
 * Ownership concrete contract
 *************************/
contract Ownership is Managed
{
    mapping (address => mapping (uint64 => uint64)) private _holdings;

    function Ownership() public 
    {
        _manager = msg.sender;
    }

    function _getHoldings(address owner, uint64 itemId) private view returns (uint64 quantity)
    {
        return _holdings[owner][itemId];
    }

    function getHoldings(address owner, uint64 itemId) public view returns (uint64 quantity)
    {
        require(isManager(msg.sender));
        return _getHoldings(owner, itemId);
    }

    function getHoldings(uint64 itemId) public view returns (uint64 quantity)
    {
        return _getHoldings(msg.sender, itemId);
    }

    event Transfer(address indexed from, address indexed to, uint64 itemId, uint64 quantity);

    function _transfer(address from, address to, uint64 itemId, uint64 quantity) private
    {
        _remove(from, itemId, quantity);
        _add(to, itemId, quantity);
    }

    function transfer(address to, uint64 itemId, uint64 quantity) public
    {
        _transfer(msg.sender, to, itemId, quantity);
    }

    event Add(address indexed to, uint64 itemId, uint64 quantity);

    function _add(address to, uint64 itemId, uint64 quantity) private
    {
        require(to != 0x0);
        require(itemId > 0);
        require(quantity >= 0);
        require(_holdings[to][itemId] + quantity >= _holdings[to][itemId]);

        _holdings[to][itemId] += quantity;

        Add(to, itemId, quantity);
    }

    function add(address to, uint64 itemId, uint64 quantity) public
    {
        require(isManager(msg.sender));
        _add(to, itemId, quantity);
    }

    function add(uint64 itemId, uint64 quantity) public
    {
        _add(msg.sender, itemId, quantity);
    }

    event Remove(address indexed from, uint64 itemId, uint64 quantity);

    function _remove(address from, uint64 itemId, uint64 quantity) private
    {
        require(from != 0x0);
        require(itemId > 0);
        require(quantity >= 0);
        require(quantity <= _holdings[from][itemId]);

        _holdings[from][itemId] -= quantity;

        Remove(from, itemId, quantity);
    }

    function remove(address from, uint64 itemId, uint64 quantity) public
    {
        require(isManager(msg.sender));
        _remove(from, itemId, quantity);
    }

    function remove(uint64 itemId, uint64 quantity) public
    {
        _remove(msg.sender, itemId, quantity);
    }
}

I also just saw Ismael's comment about ERC721 Non-Fungible Token Standards. Seems like I was on the right track but need to dig deeper into ERC721.

Follow-up question: If I were to implement an order system where buyers and sellers of items could create bids and asks, is that something I should do off-chain and only use the blockchain for the actual transfer of funds and ownership?

  • This is a very broad question. Anything can be tracked on chain (data storage on chain is relatively expensive, though). Are you asking how the smart contract would know ownership of an object if person A and B met in person and A sold the object to B without touching the chain? – flygoing Jan 16 '18 at 19:38
  • 1
    If your objects have something like a serial number, you can try to use something like ERC 721 Non-fungible Token Standard. – Ismael Jan 16 '18 at 21:07
2

If the real world object has some parameters or attributes that can be digitized and are unique to every object then it can be uploaded to a blockchain and we can track its ownership.

Suppose somebody bought an item using ether/token then you can add a event of its purchase and store its current owner. If the person wants to sell it to somebody else he must use your contract or else he will be doing a illegal transaction.

There is a startup that trace the ownership of diamonds. Since diamonds are indestructible(almost), there angles and light reflection parameters can be stored in the blockchain. This way we can check if the current owner is verified owner or not.

You can think of something like this to make your smart contract, use erc20, find some parameter that are district, make buyer as the owner of those parameter on purchase( struct => address mapping) , deliver product to him/her.

Hope this helps.:)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.