SEP101: Store values with arbitrary length

1. Summary

This SEP proposes a method to store values with arbitrary length, through a pseudo smart contract.

2. Abstract

EVM's SSTORE and SLOAD instructions access 256-bit words. At some cases, we want to store more data in a single storage slot. If we add more EVM instructions to support arbitrary-length data loading and storing, compatibility would be hurt. So a pseudo smart contract is preferred. This smart contract is psuedo because it is not implemented by EVM bytecode. Instead, it is supported natively in the full client, smartbchd. So it can directly use MoeingADS's arbitrary-length data storage. It has a predefined address: 10002.

3. Motivation

This proposal specifies the behavior of functions in this psuedo smart contract, such that developers can use it correctly.

4. Status

This SEP has been implemented since genesis.

5. Specification

5.1 Storage Agent Contract

From the caller's view, the storage agent contracts behavior is like delegated calls to the following contract:

pragma solidity 0.6.12;

contract StorageAgent {
    bytes[0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff] private data;
    function set(bytes calldata key, bytes calldata value) external {
        data[uint256(sha256(key))] = value;
    }
    function get(bytes calldata key) external view returns (bytes memory) {
        return data[uint256(sha256(key))];
    }
}

When developing smart contracts with an EVM implementation which does not support SEP101 (such as Ganache), developers can use this contract to mimic the native storage agent.

The underlying mechanism of the native storage agent is different with above solidity code. It directly uses MoeingADS's arbitrary-length data storage, so a bytes value does not take several storage slots. Instead, it only takes one slot whose location is calculated as uint256(sha256(key)). You can read its variable-length value with eth_getStorageAt.

The smart contract 10002 can only be invoked by delegatecall and callcode. staticcall and call are not allowed. In other words, the storage inside it cannot be written.

Please not the key passed to smart contract 10002 will be hashed into a 256-bit word using sha256 algorithm, and this word is the slot where value is stored. Solidity uses small integers and keccak256-hashed words as storage slots, so sha256-hashed words will not conflict with them.

External owned accounts cannot call smart contract 10002, because they are not smart contracts and have no storage slots.

5.1.1 Methods

5.1.1.1 set

function set(uint key, bytes calldata value) external;

Given a 256-bit key and arbitrary-length value, this function stores this key-value pair for the caller.

5.1.1.2 get

function get(uint key) external view returns (bytes memory);

Given a 256-bit key, this function returns the value kept for the caller. If no corresponding key-value pair was stored before, this function returns zero-length byte slice.

5.1.2 Gas Cost

Calling the set (get) method with values shorter or equal to 32 bytes, costs the same gas as SSTORE (SLOAD) instruction, respectively.

If the value is longer than 32 bytes, extra gas must be paid, which is calculated as: (value_length - 32) * COST_PER_BYTE. For the set (get) method, COST_PER_BYTE equals 75 (25), respectively.

6. License

The content is licensed under CC0.

Last updated