Accessing Private Data - demonoved/A-trial-run-in-solidity GitHub Wiki
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
//все данные на смарт контракте могут быть прочитаны
//Узнаем как же мы можем считывать данные, и разберемся с переменной хранения private
/* нельзя использовать web3 на JVM, поэтому разворачиваем на Goerli
0x534E4Ce0ffF779513793cfd70308AF195827BD31
*/
/*
хранение
- 2 ** 256 слотов
- 32 байта для каждого слота - данные хранятся последовательно в порядке обьявления
- хранение оптимизировано для экономии места, если соседние переменные помещаются в 32 байта, то они упаковываются в один слот начиная с правлого
*/
contract Vault {
//slot 0
uint public count = 123;
//slot 1
address public owner = msg.sender;
bool public isTrue = true;
uint16 public u16 = 31;
//slot 2
bytes32 private password;
// константы не используют хранилище
uint public constant someConst = 123;
// slot 3, 4, 5 ( по одному для каждого элемента массива)
bytes32[3] public data;
struct User {
uint id;
bytes32 password;
}
//slot 6 - длина массива
//начиная со слота hash(6) - элементы массива
// слот в котором хранится элемент массива = keccak256(slot) + (index * elementSize)
// slot = 6 elementSize = 2(1(uint) + 1(bytes32))
User[] private users;
// slot 7 - пустой
// записи хранятся в hash(key, slot)
// где slot = 7, key = key mapping
mapping(uint => User) private idToUser;
constructor(bytes32 _password){
password = _password;
}
function addUser(bytes32 _password) public {
User memory user = User({id: users.length, password: _password});
users.push(user);
idToUser[user.id] = user;
}
function getArrayLocation(
uint slot,
uint index,
uint elementSize
)public pure returns(uint) {
return uint( keccak256(abi.encodePacked(slot))) + (index * elementSize);
}
function getMapLocation(uint slot, uint key) public pure returns(uint){
return uint(keccak256(abi.encodePacked(key, slot)));
}
}
Давайте разберем каждую строку кода и объясним ее назначение:
-
pragma solidity ^0.8.20;
: Эта строка указывает версию компилятора Solidity, с которой совместим контракт. -
contract Vault { ... }
: Здесь начинается объявление контракта "Vault". -
uint public count = 123;
: Объявляется публичная переменная "count" типа "uint" (целое число без знака), которая инициализируется значением 123. Публичные переменные могут быть прочитаны извне контракта. -
address public owner = msg.sender;
: Объявляется публичная переменная "owner" типа "address" (адрес Ethereum), которая инициализируется значением "msg.sender". "msg.sender" представляет адрес отправителя транзакции, которая вызвала эту функцию. -
bool public isTrue = true;
: Объявляется публичная переменная "isTrue" типа "bool" (логическое значение), которая инициализируется значением "true". -
uint16 public u16 = 31;
: Объявляется публичная переменная "u16" типа "uint16" (целое число без знака шириной 16 бит), которая инициализируется значением 31. -
bytes32 private password;
: Объявляется приватная переменная "password" типа "bytes32" (динамический массив байтов длиной 32). Приватные переменные могут быть доступны только внутри контракта. -
uint public constant someConst = 123;
: Объявляется публичная константа "someConst" типа "uint", которая инициализируется значением 123. Константы не используют хранилище и их значение не может быть изменено после инициализации. -
bytes32[3] public data;
: Объявляется публичный статический массив "data" типа "bytes32" длиной 3. Этот массив может содержать 3 элемента типа "bytes32". -
struct User { ... }
: Объявляется пользовательская структура "User", которая содержит два поля: "id" типа "uint" и "password" типа "bytes32". -
User[] private users;
: Объявляется приватный динамический массив "users" типа "User", который будет хранить объекты типа "User". -
mapping(uint => User) private idToUser;
: Объявляется приватное отображение (mapping) "idToUser", которое сопоставляет целочисленные ключи типа "uint" с объектами типа "User". Маппинг позволяет эффективно хранить и получать значения по ключу. -
constructor(bytes32 _password) { ... }
: Это конструктор контракта, который принимает параметр "_password" типа "bytes32" и инициализирует приватную переменную "password" значением этого параметра. -
function addUser(bytes32 _password) public { ... }
: Это публичная функция "addUser", которая принимает параметр "_password" типа "bytes32". Функция создает новый объект типа "User" с заданным паролем и добавляет его в массив "users" и отображение "idToUser". -
function getArrayLocation(uint slot, uint index, uint elementSize) public pure returns(uint) { ... }
: Это публичная чистая (pure) функция "getArrayLocation", которая принимает параметры "slot", "index" и "elementSize" типа "uint" и возвращает значение типа "uint". Функция вычисляет местоположение элемента массива в хранилище на основе заданных параметров. -
function getMapLocation(uint slot, uint key) public pure returns(uint) { ... }
: Это публичная чистая (pure) функция "getMapLocation", которая принимает параметры "slot" и "key" типа "uint" и возвращает значение типа "uint". Функция вычисляет местоположение записи в отображении (mapping) в хранилище на основе заданных параметров.
Это основные строки кода в предоставленном вами примере. Контракт "Vault" реализует хранение данных и демонстрирует использование различных типов переменных и структур данных в Solidity.