元宇宙里的新零售(DMall)技术(前端+智能合约)验证

起因

站在今天,回头看传统企业数字化的起点,不管是大型国有企业,还是民间风云老板,都投入了极大的热情,遗憾的是,那个时候并没有人想明白这数字化到底该咋做。转眼6年,当有人模糊弄明白了这事儿的时候,企业们已都开始却步了。其实,数字化也就是件要做的事儿,做的方法也不会有啥特殊,两步即可:定清目标路径、理顺组织执行。目标包括且只能包括两个部分:建设和使用降本提效的工具、开拓和经营绑定科技的业务。组织一定是按照目标分为成本中心和业务实体两部分,其管理也一定要符合科技特征(可参见上篇文章)。这篇文章就是想举个例子说明啥是传统企业的,绑定科技的新业务。当然,对于不同的产业,新业务也不一样,这个例子仅适用于运营传统线下商业的企业。

DMall是什么

商业模式

第一步,DMall是元宇宙中的用户,购买商户投放的,土地所有者控制的建筑构件(墙、天花板、地面等)上显示的商品,的购物场景。用户、商户、土地所有者和达猫基于智能合约分配利益。
第二步,DMall是附加上元宇宙中的万达广场,即,既有分布式的购物场景,也有集中式的生活中心。增加的部分的商业模式与实体万达广场一致。
第三步,DMall会将元宇宙里的万达广场与实体万达广场融合,构建线上线下融合的生活中心。
第四步,DMall会将引领所有web2.0时代的应用进化到web3.0时代,改变数据生产和应用的模式。

技术实现

元宇宙的技术支撑包含两个方面:新前端技术(就是钱学森翻译的灵境)、去中心化的交易技术(就是基于区块链的智能合约,包括NFT、数字货币等)。DMall的核心是后者。

背景

虚拟世界里的资产运营

在这里插入图片描述

Decentraland(一个完整的元宇宙世界该有的样子)

Decentraland(分布式大陆)是一个基于以太坊区块链实现的,分布式虚拟现实平台。在Decentraland平台中,用户可以创建、体验、和变现他们的内容和应用。
Decentraland中的,可游逛的有限3D虚拟空间,被成为Land。Land是一种非同质数字化资产(NFT),它被一个以太坊智能合约维护。Land被分为Parcel,Parcel被用笛卡尔坐标系标识。这些Parcel被社区的成员们永久持有,可以用MANA(马那币)购买,MANA是Decentraland的加密数字货币。这给了用户全权控制他们创建的环境和应用的权力。这些环境和应用包括从任何静态3D场景到更可交互的应用或者游戏。
一些Parcel进一步被组织为主题社区或者District。靠将parcel组织成district,社区可以创造由共同兴趣和用途的共享空间。你可以在这个Github地址找到最初的District建议列表。组成Decentraland的内容被储存和部署通过一个分布式网络,同时,所有权和交易在以太坊区块链上被验证。

DMall为什么是有效的数字化创新

对于传统线下商业运营组织,DMall可以是其“绑定科技的业务”的选项之一:

  • 生意的本质高度一致,传统线下商业运营组织擅长在不同的城市轻资产的运营生意
  • 元宇宙是下一个流量入口,抢先者可以享受新一轮流量红利
  • 基于数字人民币实现智能合约,符合整体金融和科技导向
  • 在海外元宇宙平台,出海中国制造,与整体方向保持一致
  • 科技含量高
  • 坚决去中心化(本质是坚决拥护一个中心),阿里等大型互联网企业里的个人既得利益者不会接受跟进
  • 可进一步发展为生活中心,让个人(和国家)成为数据的主人,所有的企业都能用到数据(付费给个人)
  • 强大的生态:希壤,抖音,腾讯,omega,啫喱

技术验证

智能合约

//SPDX-License-Identifier: UNLICENSED

pragma solidity >=0.7.0 <0.9.0;

// Merchant must call MANAToken to approve DMall to spend MANA for itself first. 
// Once DMall fails to transfer MANA from merchant to others, its ads will be invalid. 
interface MANAToken {
    function approve(address _sender, uint256 _value) external returns (bool);
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
}

contract DMall {
    enum AdState { Undefined, Created, Approved, Updated, Invalid } 

    enum ClickState { Undefined, Clicked, Bought } 

    struct Ad {
        uint m2L;
        uint m2O;
        uint m2C;
        AdState state;
        mapping(address => mapping(address => ClickState)) clicks;
    }

    MANAToken manaToken;
    mapping(address => mapping(uint => Ad)) public ads;
    address public op;

    constructor(address _manaToken) {
        op = msg.sender;
        manaToken = MANAToken(_manaToken);
    }
    
    event AdCrted(address merchant, uint adId, uint m2L, uint m2O, uint m2C);
    event AdUpted(address merchant, uint adId, uint oM2L, uint oM2O, uint oM2C, uint m2L, uint m2O, uint m2C);
    event AdAppred(address merchant, uint adId);
    event AdClicked(address merchant, uint adId, address landowner, address consumer);
    event AdInvalid(address merchant, uint adId);
    event AdBought(address merchant, uint adId, address landowner, address consumer);

    function uptAd(uint _adId, uint _m2L, uint _m2O, uint _m2C) public {
        Ad storage ad = ads[msg.sender][_adId];
        if (ad.state == AdState.Undefined) {
            ad.state = AdState.Created;
            ad.m2L = _m2L;
            ad.m2O = _m2O;
            ad.m2C = _m2C;
            emit AdCrted(msg.sender, _adId, _m2L, _m2O, _m2C);
        }
        else {
            ad.state = AdState.Updated;
            uint oM2L = ad.m2L;
            uint oM2O = ad.m2O;
            uint oM2C = ad.m2C;
            ad.m2L = _m2L;
            ad.m2O = _m2O;
            ad.m2C = _m2C;
            emit AdUpted(msg.sender, _adId, oM2L, oM2O, oM2C, _m2L, _m2O, _m2C);
        }
    }

    function apprAd(address _merchant, uint _adId) public {
        require(msg.sender == op, "Only DMall operator can approve the deployment of Ad");
        require(ads[_merchant][_adId].state != AdState.Undefined && ads[_merchant][_adId].state != AdState.Approved , "The ad of merchant with the ID does not exist or has been approved");
        ads[_merchant][_adId].state = AdState.Approved;
        emit AdAppred(_merchant, _adId);
    }

    function clickAd(address _merchant, uint _adId, address _landowner) public {
        require(ads[_merchant][_adId].state == AdState.Approved, "The ad of merchant with the ID has not been approved");
        require(ads[_merchant][_adId].clicks[_landowner][msg.sender] != ClickState.Clicked, "The clicking had been paid but does not lead to buying yet");
        if (manaToken.transferFrom(_merchant, _landowner, ads[_merchant][_adId].m2L) && manaToken.transferFrom(_merchant, op, ads[_merchant][_adId].m2O) ) {
            ads[_merchant][_adId].clicks[_landowner][msg.sender] = ClickState.Clicked;
            emit AdClicked(_merchant, _adId, _landowner, msg.sender);
        }
        else {
            ads[_merchant][_adId].state = AdState.Invalid;
            emit AdInvalid(_merchant, _adId);
        }
    }

    function buyAd(address _merchant, uint _adId, address _landowner) public {
        require(ads[_merchant][_adId].clicks[_landowner][msg.sender] == ClickState.Clicked, "The consumer does not click the ad or has bought");
        if (manaToken.transferFrom(_merchant, msg.sender, ads[_merchant][_adId].m2C)) {
            ads[_merchant][_adId].clicks[_landowner][msg.sender] = ClickState.Bought;
            emit AdBought(_merchant, _adId, _landowner, msg.sender);
        }
        else {
            ads[_merchant][_adId].state = AdState.Invalid;
            emit AdInvalid(_merchant, _adId);
        }        
    }
}

Python调用智能合约示例

import time

from eth_abi.codec import ABICodec
from web3 import Web3, HTTPProvider, WebsocketProvider
from web3._utils.events import get_event_data
from web3.types import ABIEvent

import contract_abi
from web3.logs import STRICT, IGNORE, DISCARD, WARN

dmall_address = Web3.toChecksumAddress('0xD1F7012D2b5E2B8aDB02C62F6899ce01EFFD043f')
manatoken_address = Web3.toChecksumAddress('0x2a8fd99c19271f4f04b1b7b9c4f7cf264b626edb')

merchant_private_key = ''
merchant_address = '0x9a1d7Ad2C21Bb462DE2D5cdeD44ed72343AFc257'

landowner_private_key = ''
landowner_address = '0xd6Cd1Cc3E779b958eA24943EfAa2e8a8a3752863'

consumer_private_key = ''
consumer_address = '0xc5E1d07D6653e7DC935ff3efC388a074Ee266FCB'

# w3 = Web3(HTTPProvider('https://ropsten.infura.io/v3/dd4cc999659f448d905400a4e8fb4e9d'))
w3 = Web3(WebsocketProvider('wss://ropsten.infura.io/ws/v3/dd4cc999659f448d905400a4e8fb4e9d'))

# w3.eth.enable_unaudited_features()

dmall_contract = w3.eth.contract(address=dmall_address, abi=contract_abi.dmall_abi)
manatoken_contract = w3.eth.contract(address=manatoken_address, abi=contract_abi.manatoken_abi)


def m_appr_dmall(dmall, amount):
    nonce = w3.eth.getTransactionCount(merchant_address)

    txn_dict = manatoken_contract.functions.approve(dmall, amount).buildTransaction({
        'chainId': 3,
        'gas': 140000,
        'gasPrice': w3.toWei('40', 'gwei'),
        'nonce': nonce,
    })

    signed_txn = w3.eth.account.signTransaction(txn_dict, private_key=merchant_private_key)

    result = w3.eth.sendRawTransaction(signed_txn.rawTransaction)

    tx_receipt = None

    count = 0
    while tx_receipt is None and (count < 30):
        time.sleep(10)
        try:
            tx_receipt = w3.eth.get_transaction_receipt(result)

            print(tx_receipt)
        except Exception as e:
            print('error: ', e)

    if tx_receipt is None:
        return {'status': 'failed', 'error': 'timeout'}

    processed_receipt = manatoken_contract.events.Approval().processReceipt(tx_receipt, errors=IGNORE)

    print(processed_receipt)

    # output = "Address {} approved address {} with the value {}" \
    #     .format(processed_receipt[0].args.owner, processed_receipt[0].args.spender, processed_receipt[0].args.value)
    # print(output)

    return {'status': 'added', 'processed_receipt': processed_receipt}


def m_pub_ad(ad_id, m_2_l, m_2_o, m_2_c):
    nonce = w3.eth.getTransactionCount(merchant_address)

    txn_dict = dmall_contract.functions.uptAd(ad_id, m_2_l, m_2_o, m_2_c).buildTransaction({
        'chainId': 3,
        'gas': 140000,
        'gasPrice': w3.toWei('40', 'gwei'),
        'nonce': nonce,
    })

    signed_txn = w3.eth.account.signTransaction(txn_dict, private_key=merchant_private_key)

    result = w3.eth.sendRawTransaction(signed_txn.rawTransaction)

    tx_receipt = None

    count = 0
    while tx_receipt is None and (count < 30):
        time.sleep(10)
        try:
            tx_receipt = w3.eth.get_transaction_receipt(result)

            print(tx_receipt)
        except Exception as e:
            print('error: ', e)

    if tx_receipt is None:
        return {'status': 'failed', 'error': 'timeout'}

    processed_receipt = dmall_contract.events.AdCrted().processReceipt(tx_receipt)

    print(processed_receipt)

    # output = "Address {} approved address {} with the value {}" \
    #    .format(processed_receipt[0].args.owner, processed_receipt[0].args.spender, processed_receipt[0].args.value)
    # print(output)

    return {'status': 'added', 'processed_receipt': processed_receipt}


def m_pub_ad_without_reciept(ad_id, m_2_l, m_2_o, m_2_c):
    nonce = w3.eth.getTransactionCount(merchant_address)

    txn_dict = dmall_contract.functions.uptAd(ad_id, m_2_l, m_2_o, m_2_c).buildTransaction({
        'chainId': 3,
        'gas': 140000,
        'gasPrice': w3.toWei('40', 'gwei'),
        'nonce': nonce,
    })

    signed_txn = w3.eth.account.signTransaction(txn_dict, private_key=merchant_private_key)

    result = w3.eth.sendRawTransaction(signed_txn.rawTransaction)

    print(result)


def handle_event(event):
    print(event)
    print(Web3.toJSON(event))
    receipt = w3.eth.waitForTransactionReceipt(event['transactionHash'])
    print(receipt)
    # evt = get_event_data(codec, ABIEvent(contract_abi.dmall_abi), event)
    # print(evt)
    # and whatever


def log_loop(event_filter, poll_interval):
    while True:
        for event in event_filter.get_new_entries():
            handle_event(event)
        time.sleep(poll_interval)


if __name__ == "__main__":
    # event AdCrted(address merchant, uint adId, uint m2L, uint m2O, uint m2C);
    # event AdUpted(address merchant, uint adId, uint oM2L, uint oM2O, uint oM2C, uint m2L, uint m2O, uint m2C);
    # event AdAppred(address merchant, uint adId);
    # event AdClicked(address merchant, uint adId, address landowner, address consumer);
    # event AdInvalid(address merchant, uint adId);
    # event AdBought(address merchant, uint adId, address landowner, address consumer);

    #e_filter = dmall_contract.events.AdCrted.createFilter(fromBlock="latest", address='0x551ca7Ca4e41bC5F9dE5A527544Cb7a9fA533DF1')

    # e_filter = w3.eth.filter({'address': '0x551ca7Ca4e41bC5F9dE5A527544Cb7a9fA533DF1'})

    #m_pub_ad_without_reciept(4, 13, 14, 15)
    #log_loop(e_filter, 5)
    m_appr_dmall(dmall_address, 100)

Decentraland的smart item示例关键代码

    ent.addComponent(
      new OnPointerDown(
        async function () {
            // Setup steps explained in the section above
            const provider = await getProvider()
            const requestManager = new RequestManager(provider)
            const factory = new ContractFactory(requestManager, abi)
            const contract = (await factory.at(
              "0xD1F7012D2b5E2B8aDB02C62F6899ce01EFFD043f"
            )) as any
            const address = await getUserAccount()
            log(address)
        
            // Perform a function from the contract
            const res = await contract.clickAd(
              "0x9a1d7Ad2C21Bb462DE2D5cdeD44ed72343AFc257",
              0,
              "0xd6Cd1Cc3E779b958eA24943EfAa2e8a8a3752863",
			  {
				from: address,
			  }
            )
            // Log response
            log(res)
            openExternalURL("https://item.jd.com/10045659650093.html")
        },
        {
          button: ActionButton.PRIMARY,
          hoverText: locationString,
        }
      )
    )

猜你喜欢

转载自blog.csdn.net/cloudguru/article/details/124555218
今日推荐