23.06.15
DEVOTEE를 활성화 시키면
지금 작성한 커뮤니티 글에 대해 1개의 댓글을 달아줍니다.
버튼을 누르면 글 수정 시 ChatGPT가 작성한 댓글이 수정됩니다.
| 컨텐츠 유형 | 제목 | 저장일 | 삭제 |
|---|
본인인증 로그인에 실패하였습니다.
회원이 아니시거나 본인인증 등록이
완료되지 않은 사용자입니다.
이더리움 계열 스마트 컨트랙트를 개발하는 툴로 많이 사용되는 Foundry의 기능을 간단하게 소개드리겠습니다.
Foundry 공식 홈페이지 소개글
Foundry is a smart contract development toolchain.
Foundry manages your dependencies, compiles your project, runs tests, deploys, and lets you interact with the chain from the command-line and via Solidity scripts.홈페이지에서는 소스코드 빌드, Docker 이미지 이용 등 여러가지 방법을 소개하고 있지만 가장 간단하게 설치 및 설정을 할 수 있는 방법을 소개하겠습니다.
$ curl -L https://foundry.paradigm.xyz | bash위 명령어를 사용하면 foundryup이 설치되면서 forge, cast, anvil, chisel 바이너리 파일이 같이 설치됩니다.
forge : Ethereum testing framework (like Truffle, Hardhat and DappTools).
cast : Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data
anvil : Local Ethereum node, akin to Ganache, Hardhat Network.
chisel : Fast, utilitarian, and verbose solidity REPL.
$ forge init devocean
$ cd devocean위 명령어를 사용하면 기본적인 프로젝트가 생성됩니다.
$ forge build
[⠊] Compiling...
[⠘] Compiling 27 files with Solc 0.8.26
[⠃] Solc 0.8.26 finished in 749.20ms기본 생성된 컨트랙트가 빌드되고 out / cache 디렉토리가 생성
out : contract artifact (ABI) 를 담고 있음
cache : forge에서 사용하는 캐시
$ forge test
[⠊] Compiling...
No files changed, compilation skipped
Ran 2 tests for test/Counter.t.sol:CounterTest
[PASS] testFuzz_SetNumber(uint256) (runs: 256, μ: 31199, ~: 31277)
[PASS] test_Increment() (gas: 31293)
Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 5.72ms (4.78ms CPU time)
Ran 1 test suite in 183.01ms (5.72ms CPU time): 2 tests passed, 0 failed, 0 skipped (2 total tests)간단한 예시를 위해 Openzepplin에서 제공하는 기능을 사용하여 간단한 컨트랙트를 작성하겠습니다.
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.22;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract DragonERC20 is ERC20, Ownable {
constructor(address initialOwner)
ERC20("DRAGON", "D")
Ownable(initialOwner)
{}
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}
}드래곤이라는 ERC20 작성
위 코드로 워크스페이스 src에 DragonERC20.sol 생성
❗️파일을 생성한 후 다시 빌드 명령어를 입력하면 openzepplin의 파일을 찾을 수 없다는 에러가 발생합니다.❗️
Error: Compiler run failed:
Error (6275): Source "@openzeppelin/contracts/token/ERC20/ERC20.sol" not found: File not found. openzepplin/contract 라이브러리 설치가 필요
$ forge install openzeppelin/openzeppelin-contracts --no-commit #bad
$ forge install openzeppelin/openzeppelin-contracts@v5.1.0 --no-commit #good위 명령어를 입력하면 lib 디렉토리에 설치되고 버전을 명시하는 것이 좋음 (즉, 코드에서도 필요한 버전을 명시해주는 것이 좋음)
// SPDX-License-Identifier: MIT
// Compatible with OpenZeppelin Contracts ^5.0.0
pragma solidity ^0.8.22;
import {ERC20} from "@openzeppelin/contracts@v5.1.0/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts@v5.1.0/access/Ownable.sol";
... 이하 동일 코드라이브러리 위치 매핑 (remappings.txt 작성)
@openzeppelin/contracts@v5.1.0/=lib/openzeppelin-contracts/contracts/위 작업까지 진행하면 배포될 준비가 되었습니다. (상용환경에서는 테스트 코드 작성 필수❗️)
컨트랙트를 배포하기 위해서는 지갑과 배포를 하기 위해 필요한 가스가 필요합니다.
쉽게 테스트 가스(코인)을 얻을 수 있는 Avalanche Testnet(FUJI)에 배포를 진행해보겠습니다.
이더리움 계열 지갑을 생성하고 FUJI Faucet 에서 가스비를 충당합니다.
$ forge create --broadcast --rpc-url=https://api.avax-test.network/ext/bc/C/rpc --private-key=${PRIVATE_KEY} src/DragonERC20.sol:DragonERC20 --constructor-args=0x7b7074146761Af8F8b10aB9BDA2D12613a2396E5
[⠊] Compiling...
No files changed, compilation skipped
Deployer: 0x7b7074146761Af8F8b10aB9BDA2D12613a2396E5
Deployed to: 0x5fc153596Fa7793564315800B9B37DF6f8976FDE
Transaction hash: 0xa7260ca44145db621f2720839856c4a39913ddc97888cc6a20547a49b9dfcfcdflag 확인
rpc-url : 블록체인 노드 RPC URL
private-key : 지갑의 프라이빗키 (서명을 위해 필요)
constructor-args : 스마트 컨트랙트의 생성자 파라미터
결과 확인
Deployer : transaction sender
Deployed to : 배포된 컨트랙트 주소
Transaction Hash : 블록에 생성된 transaction hash
배포 결과 확인
rpc call을 통해 확인을 할 수도 있고 다양한 방법이 존재하지만 간단하게 익스플로어에서 배포된 주소에 대해서 확인을 해본다. - link
ERC20에는 소유한 토큰을 조회하는 balanceOf 함수가 존재
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);작성한 DragonERC20에는 토큰을 발행하는 mint 함수가 존재
function mint(address to, uint256 amount) public onlyOwner {
_mint(to, amount);
}해당 함수를 호출하기 위해서는 Contract의 소유주여야 함 (onlyOwner)
balanceOf는 단순 조회하는 함수여서 Transaction이 발생하지 않아도 되고 mint는 상태값을 바꾸는 함수라 Transaction이 발생해야 합니다.
cast를 이용하여 balanceOf 함수 호출 (non-tx)
$ cast call 0x5fc153596Fa7793564315800B9B37DF6f8976FDE "balanceOf(address)(uint256)" 0x7b7074146761Af8F8b10aB9BDA2D12613a2396E5 --rpc-url=https://api.avax-test.network/ext/bc/C/rpc
0cast call 은 컨트랙트 조회하는 함수를 이용할 때 사용
cast call ${CONTRACT_ADDRESS} ${CALL_METHOD_INTERFACE} ${CALL_METHOD_ARGS..}
cast를 이용한 mint 함수 호출 (tx)
$ cast send 0x5fc153596Fa7793564315800B9B37DF6f8976FDE "mint(address,uint256)" 0x7b7074146761Af8F8b10aB9BDA2D12613a2396E5 10000000000 --rpc-url=https://api.avax-test.network/ext/bc/C/rpc --private-key=${PRIVATE_KEY}
blockHash 0x5811bb810a3d51903639866742b60d8a550b142b269881cf71884f70236d02ff
blockNumber 36912969
contractAddress
cumulativeGasUsed 197009
effectiveGasPrice 1100000001
from 0x7b7074146761Af8F8b10aB9BDA2D12613a2396E5
gasUsed 70667
logs [{"address":"0x5fc153596fa7793564315800b9b37df6f8976fde","topics":["0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef","0x0000000000000000000000000000000000000000000000000000000000000000","0x0000000000000000000000007b7074146761af8f8b10ab9bda2d12613a2396e5"],"data":"0x00000000000000000000000000000000000000000000000000000002540be400","blockHash":"0x5811bb810a3d51903639866742b60d8a550b142b269881cf71884f70236d02ff","blockNumber":"0x2333f49","transactionHash":"0x267be67d52ec217497062df33cac0f036e399d370e03658a38b171f82ba706de","transactionIndex":"0x1","logIndex":"0x3","removed":false}]
logsBloom 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000020000000000000000000800010000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000400000000000000000000000010000000000000000000000020000008000000000010000000000000000100000000000000000000000000000000
root
status 1 (success)
transactionHash 0x267be67d52ec217497062df33cac0f036e399d370e03658a38b171f82ba706de
transactionIndex 1
type 2
blobGasPrice
blobGasUsed
authorizationList
to 0x5fc153596Fa7793564315800B9B37DF6f8976FDEcast send의 경우 transaction을 발생시키기 때문에 서명을 할 수 있는 privatekey가 필요합니다.
cast send 호출에 성공하면 해당 transaction에 대한 기본 정보값을 반환해줍니다.
다시 한번 balanceOf 함수 호출
$ cast call 0x5fc153596Fa7793564315800B9B37DF6f8976FDE "balanceOf(address)(uint256)" 0x7b7074146761Af8F8b10aB9BDA2D12613a2396E5 --rpc-url=https://api.avax-test.network/ext/bc/C/rpc
10000000000 [1e10]정상적으로 minting 된 것을 확인할 수 있습니다.
Foundry는 위에서 소개한 기능외에도 정말 많은 기능을 제공하고 있는 개발툴입니다.
특히 Solidity 테스트 코드를 작성하고 진행하는데 큰 도움을 줄 수 있는 도구입니다.
홈페이지와 github에서 자세히 알아볼 수 있습니다.
DEVOTEE를 활성화 시키면
지금 작성한 댓글에 AI가 댓글을 달아줍니다.