bitpro가 원문에서 글자만 모은 내용이에요. 표·그림·수식은 빠지거나 깨질 수 있어요. 전체 54쪽 중 20쪽
tId) public {
Ballot storage ballot = ballots[ballotId];
require(ballot.active, "Ballot is already closed");
ballot.active = false;
emit BallotClosed(ballotId);
}
function getBallotDetails(uint256 ballotId)
public
view
returns (
string memory name,
string[] memory options,
bool active,
uint256 totalVotes
)
{
Ballot storage ballot = ballots[ballotId];
return (ballot.name, ballot.options, ballot.active, ballot.totalVotes);
}
function getBallotResults(uint256 ballotId) public view returns (uint256[] memory results) {
Ballot storage ballot = ballots[ballotId];
uint256[] memory voteCounts = new uint256[](ballot.options.length);
for (uint256 i = 0; i < ballot.options.length; i++) {
voteCounts[i] = ballot.votes[i];
}
return voteCounts;
}
}
```
## Compile the Smart Contract
Compiling the Smart Contract will convert the Solidity code into machine-readable bytecode.
To compile the Smart Contract, run the command:
```
forge build
```
It will return the response:
```
[⠊] Compiling...
[⠢] Compiling 27 files with Solc 0.8.28
[⠆] Solc 0.8.28 finished in 2.22s
Compiler run successful!
```
You can learn more about parsing arguments using flags by reading the [Foundry book](https://book.getfoundry.sh/reference/forge/forge-build).
## Deploy Contract.
Deploying Smart Contracts to the Somnia Network is very straightforward. All you need the RPC URL and the Private Key from[ ](#user-content-fn-1)[^1]an Ethereum address which contains some STT tokens to pay for Gas during deployment. You can get some STT Tokens from the Somnia [Faucet](https://devnet.somnia.network/). Follow this [guide](https://support.metamask.io/managing-my-wallet/secret-recovery-phrase-and-private-keys/how-to-export-an-accounts-private-key/) to get your Private Key on MetaMask.\
\
To deploy the Smart Contract, run this command in the terminal:
```
forge create --rpc-url
https://dream-rpc.somnia.network
--private-key PRIVATE_KEY src/BallotVoting.sol:BallotVoting
```
You will see a status response:
```
[⠊] Compiling...
No files changed, compilation skipped
Deployer: 0xb6e4fa6ff2873480590c68D9Aa991e5BB14Dbf03
Deployed to: 0x46639fB6Ce28FceC29993Fc0201Cd5B6fb1b7b16
Transaction hash: 0xb3f8fe0443acae4efdb6d642bbadbb66797ae1dcde2c864d5c00a56302fb9a34
```
Copy the Transaction hash and paste it into the Somnia Network [Explorer](https://shannon-explorer.somnia.network/). You will find the deployed Smart Contract address.\
\
Congratulations. 🎉 You have deployed your “BallotVoting” Smart Contract to the Somnia Network using Foundry. 🎉<br>
[^1]: I would change this for "an"
# Deploy with Hardhat
Various developer tools can be used to build on Somnia to enable the Somnia mission of empowering developers to build Mass applications. One such development tool is Hardhat.\
\
[Hardhat](https://hardhat.org) is a development environment for the EVM i.e. Somnia. It consists of different components for editing, compiling, debugging, and deploying your smart contracts and dApps, all working together to create a complete development environment.\
\
This guide will teach you how to deploy a “Buy Me Coffee” Smart Contract to the Somia Network using Hardhat Development tools.
{% 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=4F9zrCsNjmE>" %}
## 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. Hardhat is installed and set up on your local machine. See [Guide](https://hardhat.org/hardhat-runner/docs/getting-started#installation).
## Initialise Hardhat Project
Start a new Hardhat project by running the following command in your Terminal:
```bash
npx hardhat init
```
This will give you a series of prompts. Select the option to “Create a TypeScript Project (with Viem)”
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2F1d19cgBgLMTfHs1n3h9V%2FHardhat1.png?alt=media&token=39635e08-e00e-4080-8946-efc6176246c4" alt=""><figcaption></figcaption></figure>
This will install the required dependencies for your project.\
\
Once the installation is complete, open the project directory and check the directories where you will find the \`contracts\` directory. This is where the Smart Contract will be added.
## Create the Smart Contract
Open the Smart Contracts folder and delete the default `Lock.sol` file. Create a new file, `BuyMeCoffee.sol` and paste the following code:
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
contract BuyMeCoffee {
event CoffeeBought(
address indexed supporter,
uint256 amount,
string message,
uint256 timestamp
);
address public owner;
struct Contribution {
address supporter;
uint256 amount;
string message;
uint256 timestamp;
}
Contribution[] public contributions;
constructor() {
owner = msg.sender;
}
function buyCoffee(string memory message) external payable {
require(msg.value > 0, "Amount must be greater than zero.");
contributions.push(
Contribution(msg.sender, msg.value, message, block.timestamp)
);
emit CoffeeBought(msg.sender, msg.value, message, block.timestamp);
}
function withdraw() external {
require(msg.sender == owner, "Only the owner can withdraw funds.");
payable(owner).transfer(address(this).balance);
}
function getContributions() external view returns (Contribution[] memory) {
return contributions;
}
function setOwner(address newOwner) external {
require(msg.sender == owner, "Only the owner can set a new owner.");
owner = newOwner;
}
}
```
## Compile the Smart Contract
To compile your contracts, you need to customize the Solidity compiler options, open the `hardhat.config.js` file and ensure the Solidity version is `0.8.28` and then run the command:
```bash
npx hardhat compile
```
It will return the response:
```
Compiling...
Compiled 1 contract successfully
```
This will compile the Solidity file and convert the Solidity code into machine-readable bytecode. By default, the compiled *artifacts* will be saved in the newly created `artifacts` directory.\
\
The next step is to deploy the contracts to the Somnia Network. In Hardhat, deployments are defined through **Ignition Modules**. These modules are abstractions that describe a deployment, specifically, JavaScript functions that process the file you want to deploy.\
\
Open the `ignition` directory inside the project root's directory, then enter the directory named `modules`. Delete the `Lock.ts` file. Create a `deploy.ts` file and paste the following code:
```typescript
import { buildModule } from "@nomicfoundation/hardhat-ignition/modules";
const BuyMeCoffee = buildModule("BuyMeCoffee", (m) => {
const contract = m.contract("BuyMeCoffee");
return { contract };
});
module.exports = BuyMeCoffee;
```
## Deploy Contract
Open the `hardhat.config.js` file and update the network information by adding Somnia Network to the list of networks. Copy your Wallet Address Private Key from MetaMask, and add it to the **accounts** section. Ensure there are enough STT Token in the Wallet Address to pay for Gas. You can get some from the Somnia [Faucet](https://devnet.somnia.network/).
```
module.exports = {
// ...
networks: {
somnia: {
url: "https://dream-rpc.somnia.network",
accounts: ["0xPRIVATE_KEY"], // put dev menomonic or PK here,
},
},
// ...
};
```
> The "**0xPRIVATE\_KEY**" is used to sign the Transaction from your EOA without permission. When deploying the smart contract, you must ensure the EOA that owns the Private Key is funded with enough STT Tokens to pay for gas. Follow this [guide](https://support.metamask.io/managing-my-wallet/secret-recovery-phrase-and-private-keys/how-to-export-an-accounts-private-key/) to get your Private Key on MetaMask.
Open a new terminal and deploy the smart contract to the Somnia Network. Run the command:
```bash
npx hardhat ignition deploy ./ignition/modules/deploy.ts --network somnia
```
You will see a confirmation message asking if you want to deploy to the Somnia Network. Answer by hitting “**y**” on your keyboard. This will confirm the deployment of the Smart Contract to the Somnia Network.
<figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2F1WJLxutkGqpORdMMV2iO%2FHardhat2.png?alt=media&token=fb2b88e6-c5ee-4521-9185-f8a8b89b8b4a" alt=""><figcaption></figcaption></figure>
Congratulations. 🎉 You have deployed your “BuyMeCoffee” Smart Contract to the Somnia Network using Hardhat. 🎉
## **Verify Your Smart Contract**
After deploying your contract, you can verify it using the [Hardhat Verify plugin](https://hardhat.org/hardhat-runner/plugins/nomicfoundation-hardhat-verify). This allows your source code to be visible and validated on the [Somnia Explorer](https://shannon-explorer.somnia.network).
#### Update `hardhat.config.ts`Add the following to your config file:
```js
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
const config: HardhatUserConfig = {
solidity: "0.8.28",
networks: {
somnia: {
url: "https://dream-rpc.somnia.network",
accounts: ["YOUR_PRIVATE_KEY"],
},
},
sourcify: {
enabled: false,
},
etherscan: {
apiKey: {
somnia: "empty",
},
customChains: [
{
network: "somnia",
chainId: 50312,
urls: {
apiURL: "https://shannon-explorer.somnia.network/api",
browserURL: "https://shannon-explorer.somnia.network",
},
},
],
},
};
```
> Store your private key in a `.env` file and import it securely to avoid hardcoding.
After deploying your contract, run the Verify command. Copy the deployed address and run:
```bash
npx hardhat verify --network somnia DEPLOYED_CONTRACT_ADDRESS "ConstructorArgument1" ...
```
Example for a contract with one string constructor arg:
```bash
npx hardhat verify --network somnia 0xYourContractAddress "YourDeployerWalletAddress"
```
Visit the [Somnia Explorer](https://shannon-explorer.somnia.network) and search for your contract address. If successful, the source code will appear under the **“Contract”** tab and show as **verified**.
<div data-full-width="true"><figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2FcN2gHJzFCQwqoaqicN3T%2FVerifiedSC-1.png?alt=media&token=5d8d8372-1646-4897-ac80-a3081c35efaa" alt=""><figcaption></figcaption></figure> <figure><img src="https://2122549367-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkYErT9t3BJtpPfejLO6I%2Fuploads%2F2u9IKT2RJTl02qpVVc2S%2FVerified-SC2.png?alt=media&token=a61d90b4-21a0-49a5-b18f-f38f9f149d9e" alt=""><figcaption></figcaption></figure></div>
The verified Smart Contracts contain the Source Code, which anyone can review for bugs and malicious code. Users can also connect with and interact with the Verified Smart Contract.
# Using the Viem Library
Somnia empowers developers to build applications for mass adoption. Smart Contracts deployed on Somnia will require front-end user interfaces to interact with them. These front-end user interfaces will require middleware libraries to establish a connection to the Somnia Network and enable interaction with Smart Contracts.\
\
In this Guide, you will learn how to use the Viem Library to establish a connection between your deployed Smart Contracts on Somnia Network and your Front-end User application. You will also learn how to perform READ and WRITE operations using Viem.\
\
[Viem](https://viem.sh) is a TypeScript interface for Ethereum that provides low-level stateless primitives for interacting with Ethereum.
{% 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=1mdtoC5Dk4E>" %}
## How does Viem enable UI interaction?
When a Smart Contract is programmed using any development tool such as RemixIDE, Hardhat or Foundry, the Smart Contract undergoes a “compilation” stage. Compiling a Smart Contract, among other things will convert the Solidity code into machine-readable bytecode. An ABI file is also produced when a Smart Contrac is compiled. ABI stand for Application Binary Interface. You can think of an ABI like the Interface that make it possible for a User Interface to connect with the Smart Contract functions in a way similar to how an API makes it possible to to connect a UI and Backend server in web2.
<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXfaRoTuAtASsyoeB7jqiU2urm-g50ESwc_Ty4iH2h7DlLcwQak0uXG-eew1-J40_S4Cr0pJwGPxgWzjCjfo4_sHX8aV20snkM5w1dcJUeGpJx8igiTMGUqatgy1OpaYTnbINqXV6A?key=HxFSDQZc_LGgImSmo9E6Cd6w" alt=""><figcaption></figcaption></figure>
## Example Smart Contract
Here is an example \`Greeter.sol\` Smart Contract:
<br>
```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, "!"));
}
}
```
## Example ABI
When the Greeter Smart Contract is compiled, below is its ABI:
<details>
<summary>ABI</summary>
<https://gist.github.com/emmaodia/bdb9b84998b1e4f3f19d0ae27c541e63>
</details>
The ABI is an array of JSON objects containing the constructor, event, and four functions in the Smart Contract. Using a Library such as Viem, you can perform READ and WRITE operations, for each of the ABI objects. You can READ the events, and other “view” only methods. You can perform WRITE operations on the “changeName” function.\
\
A cursory look at each ABI method will help you understand the function and what can be accomplished by interacting with the method. For example:
<br>
```json
{
"inputs": [ --->specifies it is an input, i.e. a WRITE function
{
"internalType": "string", ---> the data type
"name": "_newName", ---> params name
"type": "string" ---> data type
}
],
"name": "changeName", ---> function name
"outputs": [], ---> it does not have a return property
"stateMutability": "nonpayable", ---> It changes the Blockchain State without Token exchange, it simply stores information.
"type": "function" ---> It is a function.
},
```
## How to use Viem.
To use Viem, it has to be installed in the project directory where you want to perform READ and WRITE operations.\
\
First, create a directory and initialize a new project using npm.
```bash
mkdir viem-example && cd viem-example
```
Initialize a project in the directory by running the command:
```bash
npm init -y
```
Install Viem by running the following command.
```bash
npm i viem
```
## Set Up Viem
To connect to the deployed Example Greeter Smart Contract using Viem, it is necessary to have access to the Smart Contract’s ABI and its Contract Address. Viem sets up a “`transport`” infrastructure to connect with a node in the EVM Network and the deployed Smart Contracts.\
\
We will use some Viem methods to connect to your Smart Contract deployed on the Somnia Network. Viem has a \`createPublicClient\` and a \`createWalletClient\` method. The PublicClient is used to perform READ operations, while the WalletClient is used to perform WRITE operations.\
\
Create a new file `index.js` Import the method classes from the Library:
```javascript
import { createPublicClient, createWalletClient, http } from "viem";
```
The `http` is the transport protocol for interacting with the Node of the Somnia Blockchain via RPC. It uses the default Somnia RPC URL: [`https://dream-rpc.somnia.network`](https://dream-rpc.somnia.network). In the future developers can use RPC providers to avoid rate limiting.
```javascript
import { somniaTestnet } from "viem/chains"
```
## Set up PublicClient
We will start with setting up the `publicClient` to read `view` only methods. Set up a **`publicClient`** where the default Transport is `http` and `chain` is `SOMNIA` network created using the `defineChain` method.
```javascript
const publicClient = createPublicClient({
chain: somniaTestnet,
transport: http(),
})
```
## Consume Actions
Now that you have a Client set up, you can interact with Somnia Blockchain and consume Actions!\
\
An example will be to call the `greet` method on the deployed Smart Contract.\
\
To do this, we have to create a file name `abi.js` and add the exported ABI in the file.
```javascript
export const ABI = [//...ABI here]
```
In the `index.js` we can import the ABI file and start calling methods on the deployed Smart Contract. Import the ABI:
```javascript
import { ABI } from "./abi.js";
```
Set Contract Address
```
const CONTRACT_ADDRESS = "0x2e7f682863a9dcb32dd298ccf8724603728d0edd";
```
> This is an example Greeter Smart Contract deployed on Somnia Testnet
Write a Function \`interactWithContract\`:
```javascript
const interactWithContract = async () => {
try {
console.log("Reading message from the contract...");
// Read the "greet" function
const greeting = await publicClient.readContract({
address: CONTRACT_ADDRESS,
abi: ABI,
functionName: "greet",
});
console.log("Current greeting:", greeting);
} catch (error) {
console.error("Error interacting with the contract:", error);
}
};
interactWithContract();
```
Open your terminal and run the following:
```bash
node index.js
```
You will see the response from the Smart Contract logged into the Console!
<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeerGko1tZ3XeNPJPAiHOIw4DsOM8hL4HSurOu3-CgEP7dQeAUc_rbGJdXRx2jYX16DxCCUslCrEFQmmOmZJ5MDAB3-iWw8h2j4pWbbucO0YUO4Wp8i9xJ6JcI6zFUvztoPdUgbPw?key=HxFSDQZc_LGgImSmo9E6Cd6w" alt=""><figcaption></figcaption></figure>
Congratulations, you have successfully performed a READ operation on your Smart Contract deployed on Somnia.
## Set up Wallet Client
To perform a write operation, we will parse the \`createWalletClient\` method to a \`walletClient\` variable. It is important to understand that carrying out WRITE operations changes the state of the Blockchain, unlike READ operations, where you read the state of the Blockchain. So, to perform WRITE operations, a user will have to spend Gas, and to be able to spend Gas, a user will have to parse his Private Key from an EOA to give the Library masked permission to carry out transactions on behalf of the user.\
\
To read the Private Key from an EOA, we will use a Viem method:
```javascript
import { privateKeyToAccount } from "viem/accounts";
```
Then, create a variable `walletClient`
```javascript
const walletClient = createWalletClient({
account: privateKeyToAccount($YOUR_PRIVATE_KEY),
chain: somniaTestnet,
transport: http(),
});
```
> The variable \`$YOUR\_PRIVATE\_KEY\` variable can be parsed using a dotenv file.
After sending a WRITE operation, we also have to be able to read the transaction to see the state changes. We will rely on a READ method to read a transaction, \`waitForTransactionReceipt\`.\
\
Update the \`interactWithContra프로젝트로 돌아가기