【区块链安全 | 第三十八篇】合约审计之获取私有数据(二)

发布于:2025-04-13 ⋅ 阅读:(22) ⋅ 点赞:(0)

在这里插入图片描述

前言

【区块链安全 | 第三十七篇】合约审计之获取私有数据(一)中,介绍了私有数据、访问私有数据实例、Solidity 中的数据存储方式等知识,本文通过分析具体合约代码进行案例分析。

漏洞代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Vault {
    // 公共变量,可以通过 getter 函数读取
    // slot 0
    uint public count = 123;

    // 部署合约的地址会成为 owner
    // slot 1
    address public owner = msg.sender;

    // 示例布尔值和 uint16 类型变量
    // slot 1
    bool public isTrue = true;
    uint16 public u16 = 31;

    // 私有密码变量,不能通过合约外部直接访问
    // slot 2
    bytes32 private password;

    // 常量值,在部署时就固定,不可更改
    // 编译时嵌入,不占 slot
    uint public constant someConst = 123;

    // 固定长度的 bytes32 数组,长度为 3
    // slot 3、slot 4、slot 5
    bytes32[3] public data;

    // 用户结构体,包含用户 ID 和密码字段
    struct User {
        uint id;
        bytes32 password;
    }

    // 用户动态数组,仅限内部访问
    // slot 6
    User[] private users;

    // 映射:通过用户 ID 查找对应的用户结构体
    mapping(uint => User) private idToUser;

    // 构造函数,在部署时设置初始密码
    constructor(bytes32 _password) {
        password = _password;
    }

    // 添加新用户,自动分配 ID,并存储在数组和映射中
    function addUser(bytes32 _password) public {
        User memory user = User({
            id: users.length,
            password: _password
        });

        users.push(user);
        idToUser[user.id] = user;
    }

    // 工具函数:用于计算数组中元素的 storage 位置
    function getArrayLocation(
        uint slot,
        uint index,
        uint elementSize
    ) public pure returns (uint) {
        return uint(keccak256(abi.encodePacked(slot))) + (index * elementSize);
    }

    // 工具函数:用于计算映射中某个键的 storage 位置
    function getMapLocation(uint slot, uint key) public pure returns (uint) {
        return uint(keccak256(abi.encodePacked(key, slot)));
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到