# Triển khai hợp đồng bằng Foundry hoặc Hardhat

> Source: https://docs.blockvectra.com/vi/guides/deploy-contract/

## Chọn mạng

Làm theo hướng dẫn tích hợp của chuỗi đích (truy cập qua [Các chuỗi được hỗ trợ](https://docs.blockvectra.com/vi/chains/)) để tạo `network.mjs` và xuất `RPC_URL` cùng `CHAIN_ID`. Hướng dẫn cho từng chuỗi đọc chain ID và chính sách phương thức từ [GET /v1/chains](https://api.blockvectra.com/v1/chains), đồng thời giải thích token gas, việc có cần RPC riêng để phát giao dịch hay không và các thiết lập triển khai riêng của chuỗi.

Chọn một công cụ bên dưới. Cả hai đều triển khai cùng một hợp đồng nhỏ không có tham số hàm khởi tạo.

Nạp token gas gốc của mạng đã chọn cho tài khoản triển khai. Đặt `DEPLOYER_PRIVATE_KEY` an toàn trong môi trường cục bộ; không bao giờ commit giá trị này. Các lệnh sau phát một giao dịch và tiêu tốn gas.

Tạo `Hello.sol` không có tham số hàm khởi tạo:

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract Hello {
    event Ping(address indexed sender);
    function ping() external { emit Ping(msg.sender); }
    function hello() external pure returns (string memory) {
        return "hello";
    }
}
```

### Foundry

Trong dự án Foundry đã khởi tạo, đặt hợp đồng tại `src/Hello.sol` và dùng `foundry.toml` sau:

```toml
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc_version = "0.8.24"
evm_version = "paris"

[rpc_endpoints]
target = "${RPC_URL}"
```

```bash
: "${RPC_URL:?Set RPC_URL}" "${CHAIN_ID:?Set CHAIN_ID}" "${DEPLOYER_PRIVATE_KEY:?Set deployer key}"
test "$(cast chain-id --rpc-url "$RPC_URL")" = "$CHAIN_ID" || exit 1
forge build
forge create src/Hello.sol:Hello --rpc-url target \
  --chain "$CHAIN_ID" --private-key "$DEPLOYER_PRIVATE_KEY" --broadcast
```

Lưu hash giao dịch và địa chỉ đã triển khai. Dùng `cast receipt "$TX_HASH" --rpc-url "$RPC_URL"` để kiểm tra việc giao dịch được đưa vào khối và trạng thái, sau đó dùng `cast call "$CONTRACT_ADDRESS" "hello()(string)" --rpc-url "$RPC_URL"` để đọc hợp đồng. Đặt hai biến này từ kết quả triển khai.

### Hardhat 2 với ethers 6

Trong một dự án CommonJS riêng (`npm init -y`), cài đặt bằng `npm install --save-dev hardhat@2 @nomicfoundation/hardhat-ethers@3 ethers@6`. Đặt cùng hợp đồng tại `contracts/Hello.sol`. Lưu nội dung sau thành `hardhat.config.cjs`:

```js
require('@nomicfoundation/hardhat-ethers');
const { RPC_URL, CHAIN_ID, DEPLOYER_PRIVATE_KEY } = process.env;
if (!RPC_URL || !/^[1-9][0-9]*$/.test(CHAIN_ID ?? '') || !DEPLOYER_PRIVATE_KEY) {
  throw new Error('Set RPC_URL, CHAIN_ID and DEPLOYER_PRIVATE_KEY');
}
module.exports = {
  solidity: { version: '0.8.24', settings: { evmVersion: 'paris' } },
  networks: {
    target: { url: RPC_URL, chainId: Number(CHAIN_ID), accounts: [DEPLOYER_PRIVATE_KEY] },
  },
};
```

Tạo thư mục `scripts` và lưu thành `scripts/deploy.cjs`:

```js
const { ethers } = require('hardhat');
async function main() {
  const contract = await ethers.deployContract('Hello');
  console.log(contract.deploymentTransaction().hash);
  await contract.waitForDeployment();
  console.log(await contract.getAddress());
}
main().catch(error => { console.error(error); process.exitCode = 1; });
```

```bash
npx hardhat compile
npx hardhat run scripts/deploy.cjs --network target
```

`chainId` của mạng được kiểm tra đối chiếu với RPC. Xem [thiết lập mạng Hardhat 2](https://v2.hardhat.org/hardhat-runner/docs/config) và [thiết lập Foundry](https://www.getfoundry.sh/config/index.html) (truy cập ngày: 2026-10-07).

## Đọc sự kiện

Đặt `LOG_ADDRESS` thành địa chỉ đã triển khai. Làm theo phương pháp đọc sự kiện trong hướng dẫn của chuỗi đích (đăng ký WebSocket hoặc polling HTTP theo từng đoạn, tùy vào trường `ws` của chuỗi trong `/v1/chains`) để đọc các sự kiện `Ping` sau khi gọi `ping()`.
