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

Will this code create consistent storage of data in my contract? + How to use memory properly

我正在编写一个简单的合同作为示例社交媒体帖子网站的“后端”。在使用 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;
    }
        
}

所以有几个问题:

非常感谢您的帮助:)

Will this persistently store an array of posts as pushed to?

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


What is the storage limit on something like this?

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

EVM 存储中的实际存储槽位置是使用索引的散列和其他一些参数计算的(参见 docs),因此理论上存在散列冲突的可能性,但它没有'尚未在实践中得到证明。


Am I using the memory keyword properly/as needed? Do I need to use the storage keyword?

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

这是正确的用法,因为return语句只能使用memorycalldata位置。因此脚本将 RegularPostArray 从存储器加载到内存,然后 return 从内存加载它。

当您指向存储变量时,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;
}

When getRegularPosts() is called (via e.g. web3), what exactly will be returned? Will I (can I) get a JSON of everything? I'm not sure what I will receive.

这取决于 web3 库的实现(例如 JavaScript 库可以 return 与 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'
  ]
]