bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 54쪽 중 19쪽
;
import { ethers } from "hardhat";
describe("Counter Contract", function () {
it("Should increment the count by 1", async function () {
const Counter = await ethers.getContractFactory("Counter");
const counter = await Counter.deploy();
await counter.waitForDeployment();
expect(await counter.getCount()).to.equal(0);
const tx = await counter.increment();
await tx.wait();
expect(await counter.getCount()).to.equal(1);
});
it("Should emit a CountedTo event", async function () {
const Counter = await ethers.getContractFactory("Counter");
const counter = await Counter.deploy();
await counter.waitForDeployment();
await expect(counter.increment()).to.emit(counter, "CountedTo").withArgs(1);
});
});
```
{% endcode %}
### **Run Your Tests**
To run your tests, navigate to your project's root directory in the terminal and use the following command. This command will execute your test scripts using Hardhat's built-in test network and display the results.
```bash
# Run tests on the default in-process Hardhat network
npx hardhat test
# Or, start a local node in a separate terminal
npx hardhat node
# Then run tests against it
npx hardhat test --network localhost
```
***
## Forking Somnia (Testnet vs Mainnet)
*Forking is the process of copying the state of a live network, like Somnia Mainnet or Testnet, at a specific block and creating a simulation of it on your local machine. This powerful feature allows you to test how your contract will interact with other deployed contracts on the live network (such as a DEX, oracle, or NFT marketplace) using real-world data, but without any of the risk or cost.*
You can fork Shannon Testnet for faster iteration or Mainnet for production-like state. For deterministic CI, always pin a blockNumber.
{% tabs %}
{% tab title="Fork Testnet (Shannon)" %}
```ts
hardhat: {
forking: {
url: process.env.SOMNIA_RPC_TESTNET!,
blockNumber: process.env.FORK_BLOCK_TESTNET ? Number(process.env.FORK_BLOCK_TESTNET) : undefined,
},
}
```
```bash
# in-process fork
npx hardhat test
# persistent node
npx hardhat node --fork $SOMNIA_RPC_TESTNET ${FORK_BLOCK_TESTNET:+--fork-block-number $FORK_BLOCK_TESTNET}
```
{% endtab %}
{% tab title="Fork Mainnet" %}
```ts
hardhat: {
forking: {
url: process.env.SOMNIA_RPC_MAINNET!,
blockNumber: process.env.FORK_BLOCK_MAINNET ? Number(process.env.FORK_BLOCK_MAINNET) : undefined,
},
}
```
```bash
# in-process fork
npx hardhat test
# persistent node
npx hardhat node --fork $SOMNIA_RPC_MAINNET ${FORK_BLOCK_MAINNET:+--fork-block-number $FORK_BLOCK_MAINNET}
```
{% endtab %}
{% endtabs %}
> Testnet (STT) is ideal for validating flows and cheaper RPC limits; Mainnet (SOMI) reflects real contract/state and gas rules.
***
## Handy RPC Tricks (Hardhat)
These RPC methods provided by Hardhat Network allow you to manipulate the blockchain state for advanced testing scenarios.
### **Impersonate an account**
This allows you to execute transactions from any wallet address on the forked chain, which is perfect for testing functions with admin privileges or interacting with contracts using an account that holds a large amount of tokens ("whale").
{% code title="impersonate.ts" %}
```ts
import { ethers, network } from "hardhat";
async function main() {
const target = "0xYourSomniaAddress"; // account to impersonate
await network.provider.request({ method: "hardhat_impersonateAccount", params: [target] });
const signer = await ethers.getSigner(target);
await network.provider.send("hardhat_setBalance", [
target,
"0x152d02c7e14af6800000" // 1000 ether in wei
]);
console.log("Impersonating:", await signer.getAddress());
}
main().catch((e) => { console.error(e); process.exit(1); });
```
{% endcode %}
### **Time travel**
This feature lets you change the timestamp of future blocks. It's incredibly useful for testing time-dependent smart contract logic, such as vesting schedules, lock-up periods, or any functionality that relies on `block.timestamp`.
```ts
await network.provider.send("evm_setNextBlockTimestamp", [Math.floor(Date.now()/1000) + 3600]);
await network.provider.send("evm_mine");
```
### **Snapshot and Revert**
This allows you to save the current state of the blockchain and later restore it instantly. It's an efficient way to isolate your tests, ensuring that each test case starts from the same clean state without needing to restart the local node.
```ts
const id = await network.provider.send("evm_snapshot");
// ... run actions ...
await network.provider.send("evm_revert", [id]);
```
### **Reset fork**
This command resets the local Hardhat node to a fresh state forked from the blockchain. You can use it to switch to a different block number or even a different RPC endpoint without restarting your entire testing process.
```ts
await network.provider.request({
method: "hardhat_reset",
params: [{ forking: { url: process.env.SOMNIA_RPC_TESTNET!, blockNumber: Number(process.env.FORK_BLOCK_TESTNET||0) || undefined } }]
});
```
***
## Alternative: Anvil (Foundry)
{% tabs %}
{% tab title="Fork Testnet" %}
```bash
anvil --fork-url $SOMNIA_RPC_TESTNET ${FORK_BLOCK_TESTNET:+--fork-block-number $FORK_BLOCK_TESTNET} --port 8546
```
{% endtab %}
{% tab title="Fork Mainnet" %}
```bash
anvil --fork-url $SOMNIA_RPC_MAINNET ${FORK_BLOCK_MAINNET:+--fork-block-number $FORK_BLOCK_MAINNET} --port 8546
```
{% endtab %}
{% tab title="Notes" %}
Point your app/tests to `http://127.0.0.1:8546`.
Anvil JSON-RPC is Hardhat-compatible for most calls (`evm_*`). Replace `hardhat_*` with Anvil equivalents where needed.
{% endtab %}
{% endtabs %}
***
## Tips & Best Practices
* Always pin block numbers in forks for reproducibility.
* Prefer `localhost` network when you need state persistence across multiple test files.
* Keep Anvil/Hardhat on separate ports if you run both simultaneously.
* Use labels/comments in tests to describe assumptions tied to a specific fork block.
* Avoid draining RPC rate limits: cache fixtures, use snapshots, and fork testnet for most flows.
***
## Common Issues
<details>
<summary>I<strong>nsufficient funds for gas</strong></summary>
Top up native balance with \`hardhat\_setBalance\`.
</details>
<details>
<summary>N<strong>once too high / replacement underpriced</strong></summary>
Reset account state (new snapshot) or use a fresh signer.
</details>
<details>
<summary><strong>Contract already deployed at address</strong></summary>
On persistent localhost, restart node or change deployer nonce.
</details>
# Deploy with RemixIDE
The Somnia mission is to enable the building of mass-consumer real-time applications. As a Developer, you must understand the quick steps to deploy your first Smart Contract on the Somnia Network. This guide will teach you how to connect to and deploy your first Smart Contract to the Somia Network using the Remix IDE.
{% hint style="success" %}
Somnia Mainnet is LIVE. To deploy on Somnia Mainnet, you will need SOMI Tokens. Please refer to the [guide](/get-started/getting-started-for-mainnet) on Moving from Testnet to Mainnet.
{% endhint %}
{% embed url="<https://www.youtube.com/watch?v=pUQI7a_jYqo>" %}
## Pre-requisites:
1. This guide is not an introduction to Solidity Programming; you are expected to understand Basic Solidity Programming.
2. To complete this guide, you will need MetaMask installed and the Somnia Network added to the list of Networks. If you have yet to install MetaMask, please follow this guide to [Connect Your Wallet](/get-started/connect-your-wallet-to-mainnet).
[Remix](https://remix.ethereum.org/) is an IDE for Smart Contract development, which includes compilation, deployment, testing, and debugging. It makes it easy for developers to create, debug, and deploy Smart Contracts to the Somnia Network. In this example, we will deploy a Greeter Smart contract, where we can update the state of the Contract to say “Hello” + Name.
## Connect to Somnia Testnet
Ensure you are logged into your MetaMask, connected to the Somnia Testnet, and have some STT Tokens. [Get STT Tokens](broken://pages/ZcwxHL0OlYPu0mGkI25U) from the faucet.
## Create the Smart Contract
Go to the Remix IDE and create a new file. Paste the Smart Contract below:
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;
contract Greeter {
string public name;
address public owner;
event NameChanged(string oldName, string newName);
modifier onlyOwner() {
require(msg.sender == owner, "Only the owner can perform this action");
_;
}
constructor(string memory _initialName) {
name = _initialName;
owner = msg.sender;
}
function changeName(string memory _newName) external onlyOwner {
string memory oldName = name;
name = _newName;
emit NameChanged(oldName, _newName);
}
function greet() external view returns (string memory) {
return string(abi.encodePacked("Hello, ", name, "!"));
}
}
```
## Compile the Smart Contract
On the left tab, click the “Solidity Compiler” menu item and then the “ Compile Greeter.sol” button. This will compile the Solidity file and convert the Solidity code into machine-readable bytecode.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FdKcbUUf1Opv1MdtaSVl0%2Fgreeter1.png?alt=media&token=016a067e-3187-47dc-a148-6ddbf09fb71c" alt=""><figcaption></figcaption></figure>
## Deploy the Smart Contract
The Smart Contract has been created and compiled into ByteCode, and the ABI has also been created. The next step is to deploy the Smart Contract to the Somnia DevNet so that you can perform READ and WRITE operations.
On the left tab, click the “Deploy and run transactions” menu item. To deploy the Smart Contract, we will require a wallet connection. In the Environment dropdown, select the option: “Injected Provider - MetaMask”. Then select the MetaMask account where you have STT Tokens.
In the “DEPLOY” field, enter a value for the “\_INITIALNAME” variable, and click deploy.
When prompted, approve the Contract deployment on your MetaMask.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FbZnJ394qflm4jauGRoaT%2FGreeter3.png?alt=media&token=24e2ccd9-b1de-41a4-aa6b-fa71f0dc72c5" alt=""><figcaption></figcaption></figure>
Look at the terminal for the response and the deployed Smart Contract address. You can interact with the Smart Contract via the Remix IDE. Send a transaction to change the name.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2F3nbALtkWIA8XUaKdnsdO%2FGreeter4.png?alt=media&token=225da565-48df-46bb-ab1b-b056d10e13a4" alt=""><figcaption></figcaption></figure>
Congratulations. 🎉 You have deployed your first Smart Contract to the Somnia Network. 🎉
<br>
# Deploy with Thirdweb
[Thirdweb](https://thirdweb.com/) is a complete web3 development framework that offers everything you need to connect your apps or games to the Somnia network. Its service allows developers to build, manage, and analyze their Web3 applications.
This tutorial will guide you through deploying a Smart contract to the Somnia Devnet using Thirdweb’s command-line tool (\`thirdweb deploy\`). Thirdweb simplifies deployment and interaction with smart contracts on Somnia.
{% embed url="<https://www.youtube.com/watch?v=JcrsFdRKcgY>" %}
## Prerequisites
* This guide is not an introduction to Solidity Programming; you are expected to understand Basic Solidity Programming.
* To complete this guide, you will need MetaMask installed and the Somnia DevNet added to the list of Networks. If you have yet to install MetaMask, please follow this guide to Connect Your Wallet.
* Thirdweb CLI: Install globally with:
```bash
npm thirdweb install
```
## Set Up the Project
First, create a new folder for your project and initialize it.
```bash
mkdir somnia-thirdweb-example
cd somnia-thirdweb-example
```
## Write the Smart Contract
You can write your Smart Contract using the [Remix IDE](/developer/development-frameworks/deploy-with-remixide) to ensure it works. Create a file **`OpenGreeter.sol`** and add the following code:
<details>
<summary>OpenGreeter.sol</summary>
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract OpenGreeter {
string public name;
address public owner;
event NameChanged(string oldName, string newName);
constructor(string memory _initialName) {
name = _initialName;
owner = msg.sender;
}
function changeName(string memory _newName) public {
string memory oldName = name;
name = _newName;
emit NameChanged(oldName, _newName);
}
function greet() external view returns (string memory) {
return string(abi.encodePacked("Hello, ", name, "!"));
}
}
```
</details>
This is a simple Greeter Smart Contract that any address can call the **`changeName`** function. The Smart Contract has two functions:\
\
\&#xNAN;**`changeName`** - This function allows anyone to change the name variable. It stores the old name, updates the name variable, and emits the **`NameChanged`** event with the old and new names.
**`greet`** - This function returns a greeting message that includes the current name. It uses abi.encodePacked to concatenate strings efficiently.
## Deploy the Smart Contract using Thirdweb.
First, go to Thirdweb and create a profile. After you have completed the onboarding process, create a Project.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2Fu9gOGCPPoSlIjfJuC1Zw%2Fthirdweb1.png?alt=media&token=dff88e99-035e-4c73-b436-2a466bd44d60" alt=""><figcaption></figcaption></figure>
Go to the project **settings.**
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FXVHbePUtYbJknW7QN7iR%2Fthirdweb2.png?alt=media&token=c25bdefa-6641-49f7-bf6a-f1bf2eb8af96" alt=""><figcaption></figcaption></figure>
**C**opy your secret key, and keep it safe. The secret key will be used to deploy the Smart Contract.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FTILjmzz4OzFHDnBZK2kv%2FThirdweb3.png?alt=media&token=e6f5c61f-0f70-482a-a4e2-4e92bdc2f1c7" alt=""><figcaption></figcaption></figure>
Go to the terminal and paste the following command to deploy the Smart Contract:
```bash
npx thirdweb deploy -k your_secret_key
```
Select the **`solc`** option to be **`true`** in the prompts on Terminal.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FvXFViXZTG6BkZqil6k4J%2FThirdweb4.png?alt=media&token=33616b54-cb0a-4613-afff-55a368ca4976" alt=""><figcaption></figcaption></figure>
Click the link to open the User Interface in your Browser to deploy the Smart Contract.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FXxSQyhItIF4aZ9kOMiT0%2FThirdweb5.png?alt=media&token=0c09ee56-d67c-41a6-bdbd-cb692880754a" alt=""><figcaption></figcaption></figure>
Enter an initialName. Select the Network as Somnia Devnet. Check the option to import it to the list of Contracts in your Thirdweb Dashboard. Click on **`Deploy Now`** and approve the Metamask prompts.
<div><figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2F0OW54Q2s1vPVFab1onbx%2FThirdweb6.png?alt=media&token=9f3ee7f7-8c8e-4943-bf10-d87df11ff83b" alt=""><figcaption></figcaption></figure> <figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FhqmD2JWR9VzDUU4utLaG%2FThirdweb7.png?alt=media&token=8cc44893-b356-4a21-89de-ac768441dbb5" alt=""><figcaption></figcaption></figure></div>
Your Smart Contract is deployed, and you can view it on your Thirdweb Dashboard.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FgM5hUd8zY2McGaA39jRu%2FThirdweb8.png?alt=media&token=c345e5aa-bf2d-491b-bc98-9238a0eeac43" alt=""><figcaption></figcaption></figure>
Visit the Explorer section to simulate interactions with your deployed Smart Contract and carry out actual transactions.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FO8BaWj5O3A1sqAd9UghX%2FThirdweb9.png?alt=media&token=50477081-fda6-43c1-9d08-7e470e53b33a" alt=""><figcaption></figcaption></figure>
Congratulations. 🎉 You have deployed your Smart Contract to the Somnia Network using Thirdweb. 🎉
<br>
# Deploy with Foundry
Somnia empowers developers to build applications for mass adoption. Foundry is a tool for building Smart Contracts for mass adoption, making it easy for developers to create and deploy Smart Contracts to the Somnia Network.
[Foundry](https://book.getfoundry.sh/) is a blazing fast, portable and modular toolkit for EVM application development written in Rust.
This guide will teach you how to deploy a “Voting” Smart Contract to the Somia Network using Foundry.
{% hint style="success" %}
Somnia Mainnet is LIVE. To deploy on Somnia Mainnet, you will need SOMI Tokens. Please refer to the [guide](/get-started/getting-started-for-mainnet) on Moving from Testnet to Mainnet.
{% endhint %}
## Pre-requisites:
1. This guide is not an introduction to Solidity Programming; you are expected to understand Basic Solidity Programming.
2. To complete this guide, you will need MetaMask installed and the Somnia Network added to the list of Networks. If you have yet to install MetaMask, please follow this guide to [Connect Your Wallet](/get-started/connect-your-wallet-to-mainnet).
3. Foundry is installed and set up on your local machine. See [Guide](https://getfoundry.sh/)
## Initialise Foundry Project
To start a new project with Foundry, run the command:
```
forge init BallotVoting
```
This creates a new directory `hello_foundry` from the default template. Open `BallotVoting` directory, and the open the `src` directory where you will find a default `Counter.sol` solidity file. Delete the `Counter.sol` file.
## Create the Smart Contract
Create a new file inside the `src` directory and name it `BallotVoting.sol` and paste the following code:
```
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract BallotVoting {
struct Ballot {
string name;
string[] options;
mapping(uint256 => uint256) votes;
mapping(address => bool) hasVoted;
bool active;
uint256 totalVotes;
}
uint256 public ballotCount;
mapping(uint256 => Ballot) public ballots;
event BallotCreated(uint256 indexed ballotId, string name, string[] options);
event VoteCast(uint256 indexed ballotId, address indexed voter, uint256 optionIndex);
event BallotClosed(uint256 indexed ballotId);
function createBallot(string memory name, string[] memory options) public {
require(options.length > 1, "Ballot must have at least two options");
ballotCount++;
Ballot storage ballot = ballots[ballotCount];
ballot.name = name;
ballot.options = options;
ballot.active = true;
emit BallotCreated(ballotCount, name, options);
}
function vote(uint256 ballotId, uint256 optionIndex) public {
Ballot storage ballot = ballots[ballotId];
require(ballot.active, "This ballot is closed");
require(!ballot.hasVoted[msg.sender], "You have already voted");
require(optionIndex < ballot.options.length, "Invalid option index");
ballot.votes[optionIndex]++;
ballot.hasVoted[msg.sender] = true;
ballot.totalVotes++;
emit VoteCast(ballotId, msg.sender, optionIndex);
}
function closeBallot(uint256 ballo프로젝트로 돌아가기