此代码是不是会在我的合约中创建一致的数据存储? + 如何正确使用内存

Posted

技术标签:

【中文标题】此代码是不是会在我的合约中创建一致的数据存储? + 如何正确使用内存【英文标题】:Will this code create consistent storage of data in my contract? + How to use memory properly此代码是否会在我的合约中创建一致的数据存储? + 如何正确使用内存 【发布时间】:2021-12-12 09:26:28 【问题描述】:

我正在编写一个简单的合同作为示例社交媒体帖子网站的“后端”。从一个使用 web3 的前端网站,我会让用户添加帖子,然后当网页加载时,我会理想地阅读保存在合同中的所有这些帖子(并显示在网站上)。所有内容 (RegularPosts) 都应永久存储。

这是我的示例代码,我在正确的轨道上吗? Solidity 新手 -

pragma solidity >=0.7.0 <0.9.0;

contract Storage 

    struct RegularPost 
        uint256 category;
        string name; 
        string post;
        address addr;
        uint256 date;
    
    
    RegularPost[] public RegularPostArray;

    function addNewPost(uint256 _category, string memory _name, string memory _post, uint256 _date) public 
        RegularPostArray.push(RegularPost(category: _category, name: _name, post: _post, addr: msg.sender, date: _date));
        

    function getRegularPosts() public view returns (RegularPost[] memory) 
        return RegularPostArray;
    
        

所以有几个问题:

这会持久存储推送到的帖子数组吗?

这样的存储限制是多少?

我是否正确/根据需要使用了memory 关键字?我需要使用storage 关键字吗?

getRegularPosts() 被调用时(例如通过web3),究竟会返回什么?我会(我能)得到所有东西的 JSON 吗?我不确定我会收到什么。

非常感谢您的帮助:)

【问题讨论】:

【参考方案1】:

这会持久存储推送到的帖子数组吗?

是的。合约没有任何代码会重写或删除项目,并且存储是持久的。


这样的存储限制是多少?

动态大小的存储数组最多可以有2^256 项,这是索引数据类型的限制 (uint256)。

EVM 存储中的实际存储槽位置是使用索引的哈希和一些其他参数计算的(请参阅docs),因此理论上存在哈希冲突的可能性,但尚未在练习。


我是否正确/根据需要使用了memory 关键字?我需要使用storage 关键字吗?

我假设您的意思是 RegularPost[] memory 作为 getRegularPosts() 返回语句的一部分(而不是 addNewPost() 函数参数中的 string memory)。

这是一个正确的用法,因为return 语句只能使用memorycalldata 位置。所以脚本将RegularPostArray从存储加载到内存,然后从内存中返回。

当您指向存储变量时,storage 位置的示例使用在函数内部:

function updatePost(uint256 _postIndex, uint256 _newCategory) external 
    // any changes to the `post`
    // will be stored in the `RegularPostArray[_postIndex]`
    RegularPost storage post = RegularPostArray[_postIndex];
    post.category = _newCategory;

但如果您使用memory 位置,Solidity 会使用变量的内存副本,并且不会更新存储:

function notUpdatePost(uint256 _postIndex, uint256 _newCategory) external 
    // any changes to `post`
    // will NOT affect `RegularPostArray[_postIndex]`
    RegularPost memory post = RegularPostArray[_postIndex];
    post.category = _newCategory;


当 getRegularPosts() 被调用时(例如通过 web3),究竟会返回什么?我会(我能)得到所有东西的 JSON 吗?我不确定我会收到什么。

这取决于 web3 库的实现(例如,javascript 库可以以与 Python 不同的结构返回数据)及其版本。但具体来说,在web3js@1.4.0 的情况下,它是一个数组数组,其中每个内部数组都表示结构(值以数字索引和关联索引的形式重复):

[
  [
    '1',
    'a',
    'a',
    '0x86beB187A30265Ce437C0BB55f38aF21554659Ae',
    '1',
    category: '1',
    name: 'a',
    post: 'a',
    addr: '0x86beB187A30265Ce437C0BB55f38aF21554659Ae',
    date: '1'
  ],
  [
    '2',
    'b',
    'b',
    '0x86beB187A30265Ce437C0BB55f38aF21554659Ae',
    '2',
    category: '2',
    name: 'b',
    post: 'b',
    addr: '0x86beB187A30265Ce437C0BB55f38aF21554659Ae',
    date: '2'
  ]
]

【讨论】:

以上是关于此代码是不是会在我的合约中创建一致的数据存储? + 如何正确使用内存的主要内容,如果未能解决你的问题,请参考以下文章

如何从DataFrame在谷歌存储中创建一个Json文件?

在 Solidity 中创建智能合约是不是有任何成本?

如何将在我的 Javascript 中创建的字符串数组传递给 C# 代码隐藏文件?

我正在尝试在 phpmyadmin 中创建一个 sql 表,但出现 4 个错误。此代码在我工作时在我的电脑上的 phpmyadmin 中有效,但在家里的电脑上无效[关闭]

不存在时如何在mongodb中创建db?

如何在 Adob​​e AIR 中创建 Android 选项菜单? (不是Java)