Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ERC: Solana Storage Router #390

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
125 changes: 125 additions & 0 deletions ERCS/erc-7694.md
@@ -0,0 +1,125 @@
---
eip: 7694
title: Solana Storage Router
description: Cross-chain storage router protocol incorporating storage router for Solana
author: Avneet Singh (@sshmatrix), 0xc0de4c0ffee (@0xc0de4c0ffee)
discussions-to: https://ethereum-magicians.org/t/erc-7694-solana-storage-router/19706
status: Draft
type: Standards Track
category: ERC
created: 2024-04-18
---

## Abstract
The following standard is an extension to the cross-chain storage router protocol introducing storage router for Solana.

## Motivation
[EIP-7700](./eip-7700) introduces three external routers for routing storage to L1 contracts, L2s and databases. This document extends that specification by introducing a fourth storage router targeting Solana as the storage provider.

L2s and databases both have centralising catalysts in their stack. For L2s, this centralising agent is the shared security with Ethereum mainnet. In case of databases, the centralising agent is trivial; it is the physical server hosting the database. In light of this, a storage provider that relies on its own independent consensus mechanism is preferred. This specification instructs how the clients should treat storage calls made to the Solana router.

Solana is a low cost L1 solution that is supported alongside Ethereum by multiple wallet providers. There are several chain-agnostic protocols on Ethereum which could benefit from direct access to Solana blockspace; ENS is one such example where it can serve users of Solana via its chain-agnostic properties while also using Solana's own native storage. This development will encourage more cross-chain functionalities between Ethereum and Solana at core.

## Specification
A Solana storage router `StorageRoutedToSolana()` requires the hex-encoded `programId` and the manager `account` on the Solana blockchain. `programId` is equivalent to a contract address on Solana while `account` is the manager wallet on Solana handling storage on behalf of `msg.sender`.

```solidity
// Revert handling Solana storage router
error StorageRoutedToSolana(
bytes32 programId,
bytes32 account
);

// Generic function in a contract
function setValue(
bytes32 node,
bytes32 key,
bytes32 value
) external {
// Get metadata from on-chain sources
(
bytes32 programId, // Program (= contract) address on Solana; hex-encoded
bytes32 account // Manager account on Solana; hex-encoded
) = getMetadata(node); // Arbitrary code
// programId = 0x37868885bbaf236c5d2e7a38952f709e796a1c99d6c9d142a1a41755d7660de3
// account = 0xe853e0dcc1e57656bd760325679ea960d958a0a704274a5a12330208ba0f428f
// Route storage call to Solana router
revert StorageRoutedToSolana(
programId,
account
);
};
```

Since Solana natively uses `base58` encoding in its virtual machine setup, `programId` values that are hex-encoded on EVM must be `base58`-decoded for usage on SVM. Clients implementing the Solana router must call the Solana `programId` using a Solana wallet that is connected to `account` using the `base58`-decoded (and casted to appropriate data type) calldata that it originally received.

```js
/* Pseudo-code to write to Solana program (= contract) */
// Decode all 'bytes32' types in EVM to 'PubKey' type in SVM
const [programId, account, node, key, value] = svmPubkey([programId, account, node, key, value])
// Instantiate program interface on Solana
const program = new program(programId, rpcProvider);
// Connect to Solana wallet
const wallet = useWallet();
// Call the Solana program using connected wallet with initial calldata
// [!] Only approved manager in the Solana program should call
if (wallet.publicKey === account) {
await program(wallet).setValue(node, key, value);
}
```

In the above example, EVM-specific `bytes32`-type variables `programId`, `account`, `node`, `key` and `value` must all be converted to SVM-specific `PubKey` data type. The equivalent `setValue()` function in the Solana program is of the form

```rust
// Example function in Solana program
pub fn setValue(
ctx: Context,
node: PubKey,
key: PubKey,
value: PubKey
) -> ProgramResult {
// Code to verify PROGRAM_ID and rent exemption status
...
// Code for de-serialising, updating and re-serialising the data
...
// Store serialised data in account
// [!] Stored data must be mapped by node & account
...
}
```

Since EVM and SVM have differing architectures, it is important to define precise data type castings from EVM to SVM. Some pre-existing custom but popular data types in SVM already equate to common EVM data types such as `PubKey` and `bytes32` respectively. This specification requires the following implementation of EVM to SVM type casting:

| EVM | SVM |
|:---------------:|:------------------:|
| `uint8` | `u8` |
| `uint16` | `u16` |
| `uint32` | `u16` |
| `uint64` | `u64` |
| `uint128` | `u128` |
| `uint256` | `u256`† |
| `bytes1` | `bytes: [u8; 1]` |
| `bytes2` | `bytes: [u8; 2]` |
| `bytes4` | `bytes: [u8; 4]` |
| `bytes8` | `bytes: [u8; 8]` |
| `bytes16` | `bytes: [u8; 16]` |
| `bytes32` | `PubKey` |
| `bytes` | `bytes: Vec<u8>` |
| `string` | `String` |
| `address` | `bytes: [u8; 20]` |

> † `u256` is not available natively in SVM but is routinely implemented via `u256` crate in Rust

Using this strategy, most - if not all - current use-cases of `StorageRoutedToSolana()` are accounted for.

## Rationale
`StorageRoutedToSolana()` works in a similar fashion to `StorageRoutedToL2()` in [EIP-7700](./eip-7700) in the sense that the client needs to be pointed to a certain contract on another chain by the revert event. Other than that, the only technical difference is casting between EVM and SVM data types.

## Backwards Compatibility
None.

## Security Considerations
None.

## Copyright
Copyright and related rights waived via [`CC0`](../LICENSE.md).