> For the complete documentation index, see [llms.txt](https://docs.rome.builders/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rome.builders/vi/huong-dan-cho-nha-phat-trien/open-to-solana-users.md).

# Mở hợp đồng của bạn cho người dùng Solana

Triển khai một hợp đồng Solidity trên Rome (testnet Hadrian, mainnet Rubicon) và mở nó cho các ví Solana — hợp đồng cần gì, người dùng ví Solana gọi nó như thế nào, địa chỉ theo từng mạng, và một chiến dịch ra mắt ch

Một lần triển khai, hai loại người dùng. Một hợp đồng trên Rome được cả người dùng MetaMask với khóa EVM của họ và người dùng ví Solana (ví dụ như Solflare) với khóa Solana của họ truy cập — cùng địa chỉ, cùng trạng thái. Trang này là lộ trình đầu cuối: triển khai, làm cho hợp đồng sẵn sàng cho Solana, nối lane Solana trong ứng dụng của bạn và đưa lên mainnet.

## 1. Triển khai trên mạng bạn muốn

Các chain Rome là đích EVM tiêu chuẩn: Hardhat, Foundry, viem và ethers hoạt động không cần sửa đổi (hướng dẫn đầy đủ trong [Triển khai Hợp đồng Solidity](/vi/huong-dan-cho-nha-phat-trien/deploy-solidity.md)).

| Mạng                                            | Mã Chain | RPC                                         | Trình khám phá                                                                        | Token gas | Cách lấy gas                                                                                                                                               |
| ----------------------------------------------- | -------- | ------------------------------------------- | ------------------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [**Rubicon**](/vi/mang/rubicon.md) (mạng chính) | `7531`   | `https://rubicon.mainnet.romeprotocol.xyz/` | [via-rubicon.mainnet.romeprotocol.xyz](https://via-rubicon.mainnet.romeprotocol.xyz/) | USDC      | Bridge USDC từ Ethereum (CCTP) hoặc từ Solana với [Cầu Rome](https://bridge-api.mainnet.romeprotocol.xyz/); nó sẽ đến dưới dạng gas                        |
| **Hadrian** (mạng thử nghiệm)                   | `200010` | `https://hadrian.testnet.romeprotocol.xyz/` | [via-hadrian.testnet.romeprotocol.xyz](https://via-hadrian.testnet.romeprotocol.xyz/) | test USDC | Bridge test USDC từ một testnet ([Faucets](/vi/tai-nguyen/faucets.md)) hoặc wrap từ ví Solana devnet trong [Rome App](https://app.devnet.romeprotocol.xyz) |

Gas là USDC với 18 chữ số thập phân ở phía EVM; không có faucet Rome trên bất kỳ mạng nào. Ghi dữ liệu tốn gas hơn trực giác về Ethereum gợi ý, vì phần lớn chi phí là tạo tài khoản Solana: một người nhận chưa từng dùng, một tài khoản token mới, một hợp đồng đã triển khai. Hãy dùng `eth_estimateGas`, điều mà tooling tiêu chuẩn đều làm, và đừng bao giờ hardcode 21.000. Được đo trên Hadrian, triển khai một hợp đồng 10 byte ước tính và dùng 1.147.921 gas, và một lần chuyển native tới một địa chỉ chưa từng dùng là 1.086.961, so với 21.000 cho một lần chuyển tới địa chỉ đã tồn tại. Rome tính đúng lượng gas thực sự đã dùng, và trong các phép đo này con số thực tế chưa bao giờ vượt quá ước tính. Nạp vài USDC trước lần triển khai đầu tiên. Sau đó xác minh source trên explorer ([Xác minh hợp đồng](/vi/huong-dan-cho-nha-phat-trien/verify-contracts.md); trình xác minh mainnet là `https://verify.mainnet.romeprotocol.xyz`).

Phát triển trên Hadrian, rồi triển khai lại cùng các artifact đó lên Rubicon với chain id và các địa chỉ wrapper mainnet được thay; không có gì trong hợp đồng thay đổi giữa các mạng. Rubicon chưa có trong registry công khai, `create-rome-app` hoặc `rome-cli` nên các công cụ đọc giá trị chain từ đó không thể nhắm tới nó; hãy điền các giá trị thủ công từ [Rubicon](/vi/mang/rubicon.md). Gas trên Rubicon là USDC thật với mức giá gas khoảng gấp mười lần Hadrian, nên một lần triển khai ở đó tốn tiền thật.

## 2. Điều gì làm cho một hợp đồng sẵn sàng cho Solana

Danh tính EVM của người dùng Solana là **địa chỉ tổng hợp**, `keccak256(solana_pubkey)[12:]`: một `msg.sender`, với một nonce bình thường. Phần lớn hợp đồng không cần thay đổi gì cả. Ba điều quan trọng là:

* **Nhận giá trị dưới dạng ERC-20, không phải `msg.value`.** Tiền của người dùng Solana là các token SPL trong ví của họ, được thấy ở phía EVM như wrapper của token (`wUSDC`, `wETH`, `wSOL`). Synthetic không giữ gì ở trạng thái nghỉ và tài sản của người dùng đi vào dưới dạng wrapper, vì vậy hãy lấy bằng `transferFrom` sau một `approve` và trả lại bằng `chuyển`. Mỗi người dùng cấp cho wrapper quyền SPL delegate một lần trước lần pull đầu tiên ([Một lần: cấp cho wrapper](/vi/huong-dan-cho-nha-phat-trien/dual-lane-app.md#one-time-grant-the-wrapper)). Một `có thể nhận thanh toán` entry point chỉ hoạt động sau khi synthetic đã được cấp gas native ( `rome_composeExternalDepositV1`của đường relay), điều mà mô hình fund-and-sweep không làm. Một vault ERC-20, AMM hoặc thị trường cho vay sẵn có đã có đúng hình dạng cần thiết.
* **Hãy dùng các wrapper chính thống.** Mỗi chain có một wrapper cho mỗi mint; các địa chỉ nằm trong [Địa chỉ Hợp đồng](/vi/tai-lieu-tham-khao/contract-addresses.md) (Hadrian cũng có trong [registry](https://github.com/rome-protocol/rome-registry)công khai). Hãy trỏ constructors tới những địa chỉ đó; đừng tự triển khai wrapper của riêng bạn.
* **Phù hợp với ngân sách atomic nơi một ví ký.** Một ví Solana ký một giao dịch Solana, nên một lệnh ở Solana-lane phải vừa với nó: khoảng 1,4M compute unit, 64 accounts, 4 KB ([Ràng buộc](/vi/cac-khai-niem-cot-loi/constraints.md)). Được đo trên Hadrian: một lần chuyển, một lần approve và một lệnh cung cấp Aave đều vừa; một lần swap Uniswap V3 vừa với rất ít dư địa (khoảng 1,24M CU); một lần vay Aave thì không và sẽ đi theo đường relay ở phần tiếp theo. Đo bằng `computeUnitsConsumed`trên receipt của Solana, bằng cách yêu cầu giao dịch với `maxSupportedTransactionVersion: 1` (các chặng Rome là giao dịch v1; nếu không có nó thì trường này sẽ đọc là 0).

Những gì bạn không cần: một chương trình Solana, một bridge, một lần triển khai thứ hai, hoặc bất kỳ Solidity đặc thù nào của Rome. Nếu hợp đồng cũng gọi các chương trình Solana thông qua precompile, xem [Gọi Solana từ EVM](/vi/huong-dan-cho-nha-phat-trien/call-solana-from-evm.md).

## 3. Để một ví Solana gọi nó

Đường EVM của ứng dụng bạn không đổi (MetaMask + `submitRomeTx`, hoặc viem/ethers thuần). Với đường Solana có hai dạng.

**Lane SDK — một giao dịch Solana v1 cho mỗi lời gọi.** [`@rome-protocol/sdk`](https://github.com/rome-protocol/rome-sdk-ts) (`submitRomeTxV1`) để proxy tạo một giao dịch Solana v1 cho lời gọi EVM của bạn (tối đa 64 accounts và 4 KB, không có address lookup table; không có instruction ComputeBudget, ví kho bạc hay khám phá account nào trong code của bạn). Ví ký hai lần bằng cùng một khóa: trước hết là một thông điệp ủy quyền dễ đọc (`Rome authorization` trên một dòng, `0x` và hash giao dịch EVM ở dòng tiếp theo), mà chain kiểm tra thông qua chương trình Ed25519, rồi sau đó là giao dịch. Ứng dụng gửi giao dịch đã ký tới Solana RPC; lời gọi trả về hash giao dịch EVM và receipt của nó. Trước khi ví ký giao dịch, SDK sẽ kiểm tra nó: payer là signer duy nhất, chỉ chương trình Rome và trình xác minh Ed25519 được chạy, instruction Rome mang đúng lời gọi mà người dùng đã ủy quyền, và không có priority fee. Mọi thứ khác đều bị từ chối.

Nếu một lời gọi không vừa trong một giao dịch, composer sẽ từ chối nó và SDK chuyển nó cho proxy để relay, với cùng chữ ký ủy quyền, nên người dùng vẫn chỉ thấy một prompt ủy quyền. Khi đó kết quả sẽ có `route: "relay"`. Các quy tắc cho lời gọi được relay và lời gọi dài nằm trong [Các lệnh gọi được chuyển tiếp và lệnh gọi dài](/vi/huong-dan-cho-nha-phat-trien/call-evm-from-solana.md#relayed-calls-and-long-calls). Một lời gọi được relay được thanh toán bằng gas native của chain, nên synthetic cần có số dư gas: `fundSyntheticGas(deps, amountWei)` di chuyển token gas của chain (USDC trên Hadrian và Rubicon) từ tài khoản token của ví vào đó, trong một giao dịch v1 được ví ký.

Chặng fund (`buildFundLeg`) và việc tạo tài khoản token của ví trước một lần sweep đều là các instruction Solana thuần túy; `submitSolanaInstructionsV1` cũng gửi chúng dưới dạng giao dịch v1, được ký bởi cùng wallet signer, không có proxy tham gia. Lời gọi riêng của sweep (`buildSweepLeg`, `HelperProgram.transfer_spl`) đi qua `submitRomeTxV1` giống như bất kỳ lời gọi nào khác, và proxy tìm các tài khoản token. `submitRomeTxV1` không tự tạo tài khoản của synthetic mới: trước lời gọi di chuyển giá trị đầu tiên, hãy kiểm tra `isSyntheticProvisioned(...)` và, nếu nó là false, hãy gửi `buildCreatePdaCall(synthetic)` qua `submitRomeTxV1` một lần. Hướng dẫn đầy đủ về nạp tiền và rút tiền kèm code nằm trong [Xây dựng một ứng dụng hai làn](/vi/huong-dan-cho-nha-phat-trien/dual-lane-app.md); cơ chế nằm trong [Gọi EVM từ Solana](/vi/huong-dan-cho-nha-phat-trien/call-evm-from-solana.md). Cách trước đó `submitRomeTxSolanaLane`, nơi xây dựng một giao dịch Solana kiểu legacy ở client, vẫn còn trong SDK như đường cũ hơn.

**Nguồn gốc của từng `deps` giá trị.** Đối tượng `deps` của SDK có năm trường bắt buộc (các trường còn lại, như `fetchImpl` và các timeout, là tùy chọn). Bốn trường đến từ chain và một trường từ ví:

| `deps` trường | Nguồn gốc                                                                                                        | Registry getter (`@rome-protocol/registry` v0.2.0)                                                            |
| ------------- | ---------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `proxyUrl`    | RPC URL của chain                                                                                                | `getChain(chainId).rpcUrl`                                                                                    |
| `chainId`     | chain ID                                                                                                         | `getChain(chainId).chainId`                                                                                   |
| `programId`   | program ID của Rome mà chain chạy trên đó                                                                        | `getChain(chainId).romeEvmProgramId`                                                                          |
| `connection`  | một Solana RPC cho cluster của chain, nơi giao dịch đã ký được gửi tới (devnet cho Hadrian, mainnet cho Rubicon) | `getChain(chainId).solana.rpc` (một URL devnet công khai cho Hadrian); với mainnet hãy dùng RPC của riêng bạn |
| `signer`      | của ví `LaneSigner`, hoặc một `Keypair` trong các script                                                         | không có                                                                                                      |

Các builder của các chặng nhận các giá trị không nằm trong `deps`. `mint` của chúng (gọi là `usdcMint` trong walkthrough) là mint Solana của token gas, lấy từ `getTokens(chainId)` (entry có `kind: "gas"`, trường `mintId`). Địa chỉ wrapper wUSDC không phải là input của builder chặng; bạn dùng nó cho các lời gọi ERC-20, và nó là entry có `kind: "spl_wrapper"` và symbol `wUSDC` (trường `address`). Registry bao phủ Hadrian. Với Rubicon, hãy điền thủ công: `proxyUrl` `https://rubicon.mainnet.romeprotocol.xyz/`, `chainId` `7531`, `programId` `RomePq9X3iAoTr813HR7uRarafFDUJty6GdiEceYpzX`, `mint` `EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v`, wrapper từ bảng ở phần tiếp theo, và một Solana mainnet RPC cho `connection`. [Rubicon](/vi/mang/rubicon.md) có danh sách đầy đủ.

**Các endpoint external-V1 của proxy — cùng lane đó nhưng không qua SDK.** SDK bọc phần compose atomic, relay và nạp gas (`fundSyntheticGas`). Các phương thức RPC thô vẫn còn cho những client không dùng SDK, và chúng bao gồm compose lặp, điều mà SDK không bọc. Ví ký một thông điệp Ed25519 cho lời gọi (dạng dễ đọc `Rome authorization\n0x<hash>` hoặc hash thô), và proxy hoặc là compose các giao dịch Solana để ví ký (`rome_composeUnsignedAtomicV1`, `rome_composeUnsignedIterativeV1` + `rome_submitSignedV1Plan`) hoặc tự chạy toàn bộ quá trình với một chữ ký ví (`rome_relayUnsignedV1`, sau một `rome_composeExternalDepositV1` (của SDK `fundSyntheticGas`) để cấp vốn cho số dư gas của synthetic; các lời gọi được relay sẽ tiêu tốn từ đó, vì vậy hãy nạp thêm khi số dư thấp). Hình dạng phương thức trong [Hỗ trợ JSON-RPC](/vi/tai-lieu-tham-khao/json-rpc.md); các quy tắc ủy quyền trong [Gọi EVM từ Solana](/vi/huong-dan-cho-nha-phat-trien/call-evm-from-solana.md#the-external-v1-endpoints). Hãy dùng relay cho mọi thứ mang tính lặp, và dùng lane SDK cho mọi thứ vừa khuôn.

Dù bằng cách nào, hợp đồng cũng thấy một giao dịch bình thường từ địa chỉ synthetic và người dùng không bao giờ giữ khóa EVM.

## 4. Địa chỉ wrapper theo từng mạng

| Mạng             | `wUSDC` wrapper                              | Các wrapper khác                                                                                         |
| ---------------- | -------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Rubicon (7531)   | `0x0952d233b0c254cd375f3bfb3e5869c1a906f9b3` | `wETH` `0x01e8b3573da1d4b7b4b1ce0932cf07c8af0c92e9`, `wSOL` `0xc4e29e0f726a906e93277cbbc37bf27a9848a113` |
| Hadrian (200010) | `0xbce339ba4c3a8de3bb8af1c5539e6ac11da3112d` | `wETH` `0x02aeace038269f9961c93d04dcacd6fb3adfa55f`, `wSOL` `0x39f36444fcb79b3e691544aee2a832ebef54ca9f` |

Token gas native xuất hiện dưới dạng `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee` trong danh sách token; nó không phải là một hợp đồng ERC-20. Wrapper mang số chữ số thập phân của SPL mint, không phải 18: wUSDC 6, wETH 8, wSOL 9.

## 5. Danh sách kiểm trước khi ra mắt

1. Đã triển khai trên Hadrian; đường EVM hoạt động từ MetaMask.
2. Mọi entry point di chuyển giá trị đều dựa trên ERC-20 và trỏ tới wrapper chính thống của chain.
3. Một ví Solana ký các giao dịch v1 (Solflare hiện làm được trên devnet; Phantom thì chưa) hoàn tất vòng đi-về đầy đủ trên Hadrian: provision synthetic (`create_pda`, một lần) → fund leg → grant → approve → call → sweep leg, bằng lane SDK; hoặc đường relay nếu lời gọi là lặp.
4. Của mỗi lời gọi ở Solana-lane `computeUnitsConsumed` được đọc từ receipt của Solana và nằm dưới ngân sách atomic, hoặc lời gọi được định tuyến qua relay.
5. Việc cấp quyền wrapper nằm trong luồng nạp tiền đầu tiên của ứng dụng bạn cho cả hai lane: `isEnabled(user)` được kiểm tra và `approve_spl` được gửi một lần khi nó là false ([Một lần: cấp cho wrapper](/vi/huong-dan-cho-nha-phat-trien/dual-lane-app.md#one-time-grant-the-wrapper)).
6. Source đã được xác minh trên explorer.
7. Đã triển khai lại trên Rubicon với các địa chỉ wrapper mainnet. Rubicon không có trong registry, nên các `deps` giá trị được điền thủ công từ [Rubicon](/vi/mang/rubicon.md). Cùng một vòng đi-về được chạy một lần với tiền thật, dùng một ví mà bạn đã kiểm tra có thể ký giao dịch v1 trên mainnet.

## Tiếp theo là gì

* [Xây dựng một ứng dụng hai làn](/vi/huong-dan-cho-nha-phat-trien/dual-lane-app.md) — ví dụ vault, từng bước, cả hai ví
* [Gọi EVM từ Solana](/vi/huong-dan-cho-nha-phat-trien/call-evm-from-solana.md) — địa chỉ synthetic, khám phá account, các endpoint external-V1
* [Triển khai Hợp đồng Solidity](/vi/huong-dan-cho-nha-phat-trien/deploy-solidity.md) · [Xác minh hợp đồng](/vi/huong-dan-cho-nha-phat-trien/verify-contracts.md) · [Địa chỉ Hợp đồng](/vi/tai-lieu-tham-khao/contract-addresses.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.rome.builders/vi/huong-dan-cho-nha-phat-trien/open-to-solana-users.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
