{"content":{"title":"sui move动态字段练习（5）- 总结与思考","body":"## 引言  \r\n之前几篇文章，我们用sui move动态字段模拟solidity映射，实现了一个类似erc20的代币，这使我更加深刻地理解了sui move和solidity编程特性和编程思想的区别。下面是我的总结与思考。  \r\n\r\n## 总结  \r\n首先，sui与solidity的编程特性有很大差异。  \r\n  \r\n### solidity\r\n  \r\nsolidity是面向以太坊虚拟机（EVM）的合约编程语言，以太坊状态树储存了各个账号下的状态，而合约账户是由智能合约定义转变状态的规则。  \r\n例如在同质化代币的实现中，solidity需要使用映射这一类型储存各个账户的余额，代币被用储存在合约账户的数字替代，实际上持有代币的余额就是合约账户下储存的数字。  \r\n比如，小蓝要查询自己拥有多少代币，就需要查询代币合约下以小蓝地址为键的映射的值。小蓝要向小红转账10个代币，合约会先检查小蓝的余额是否大于转账数额，如果大于，就会将小蓝余额的对应值减去10，将小红余额对应值加10.  \r\n  \r\n### sui\r\n  \r\nsui是面向资源编程。资源是具有key能力的对象，这意味它可以在全局存储中用做键，资源都具有所有者属性来声明其所有权。所有权分为：被地址拥有，被另一个资源拥有，可变的共享，不可变的共享。而sui move中module可以称为合约，它规定了相应资源的生成，销毁，查询等规则，多个module可以部署在一个package下。只有module才能创建资源，只有资源的拥有者才能在交易中使用资源（共享资源除外），只有创建资源的module才能对资源内的属性进行改变。  \r\n  \r\n与solidity不同的是，sui中可以将余额封装后创建Token资源，这样Token资源的所有者就是Token的持有者，对Token具有使用权。相比于单纯数字的增减，持有者真正拥有了数字资产。  \r\n  \r\n虽然Sui是纯静态的语言，但是泛型为其提供了很大的灵活性。在solidity中，我们如果想要发行多种Token，就需要部署多个合约，分别储存不同代币的余额状态。而在sui中，我们只需要使用泛型，就可以使用一个module发行相同规则的不同代币。  \r\n  \r\n在分析下solidity映射与sui动态字段的区别  \r\n要深入理解solidity的映射，我们需要对以太坊合约的储存布局有所了解。以太坊中每个特定地址的智能合约都有自己的\"储存\"，储存是一个 2*256 ✖ 2*256大小的键值映射  \r\n这是一个很大的数字，但我们不需要担心它会占用太多空间，因为大部分的储存都未被使用，只有在非零值被写入时，才会被写入数据库。  \r\n我们将每一个储存的值是32字节，我们叫它插槽。每一个储存的键也是32字节大小，键的范围为0 ~ 2*256-1。那第一个插槽就成为slot（0），第二个插槽为slot（1），... ，第n个插槽就是slot（n-1）。  \r\n而在solidity中，映射在储存中的布局遵循特定的规则。  \r\n首先solidity的映射类型本身顺序占据一个插槽slot（i），映射的键为k, 则此映射的值会被储存在keccak256（k，p），我们可以根据此规则很轻松的找到相应值的位置  \r\n例如：  \r\n```solidity\r\n    contract ERC20{\r\n        mapping (address => uint256) balanceOf;\r\n    }\r\n```\r\nbalanceOf储存映射储存对应地址的代币余额\r\n我们知道小蓝的地址为0x312bEeF78F3efa18cc4B94D489fCD43fEb5BbA9E，那么小蓝代币余额储存的计算：  \r\n1. balanceOf映射自身顺序占据slot（0）， p = 0 ;\r\n2. 键为小蓝的地址， k = 0x312bEeF78F3efa18cc4B94D489fCD43fEb5BbA9E\r\n3. 余额储存在 slot( keccak256(abi.encode(address(0x312bEeF78F3efa18cc4B94D489fCD43fEb5BbA9E), 0)) )  \r\n这样来看，当一个映射的储存记录无限多时，取出一个键对应的值事件复杂度为O(1).  \r\n  \r\n在sui move中，我们使用的table，bag等类型的底层实现都为动态字段  \r\n添加一个动态字段，实质上是为对象添加了一个子对象  \r\n```rust\r\n        let field = Field {\r\n            id: object::new_uid_from_hash(hash),\r\n            name,\r\n            value,\r\n        };\r\n        add_child_object(object_addr, field)\r\n```\r\n## 结语\r\n综上，sui的编程特性确定了sui的编程风格，sui官方实现的同质化代币coin很好的体现了sui的编程特性，泛型的灵活运用，无需使用数字来表示所有者对资产的持有，而是通过将余额封装为coin资源使所有者持有，比起在sui中模拟映射，不仅便利，而且安全（减少了出现合约编写的逻辑漏洞的可能）。因此，我才说'本例实现仅用于学习动态字段，由于访问gas和便捷性不强，无法用于生产。在sui move中使用的同质化代币请使用官方标准库中内置的coin'."},"author":{"user":"https://learnblockchain.cn/people/18488","address":null},"history":null,"timestamp":1710509994,"version":1}