GitHub Repo: - https://github.com/PradhumnaPancholi/Figbot
Nè mọi người! Cách đây ít lâu, tôi đã tìm hiểu Dapp Tools vì nó có các công cụ tuyệt vời để phát triển và kiểm tra các hợp đồng thông minh. Và mặc dù tôi yêu thích trải nghiệm, tôi sớm biết rằng nó đang trong giai đoạn phát triển bí mật. Điều này có nghĩa là người dùng bình thường / cá nhân không thể phụ thuộc vào các nhà bảo trì để được hỗ trợ và cập nhật.
Sau đó, tôi tình cờ gặp Foundry . Nó có mọi thứ mà Dapp Tools cung cấp ngoài việc thực thi biểu tượng được tích hợp sẵn (điều này không thành vấn đề đối với tôi khi tôi sử dụng Manticor e by Trail of Bits). Và đây là liên quan đến kiểm toán do đó không phải là trở ngại trong việc phát triển hợp đồng thông minh bởi bất kỳ sự tưởng tượng nào.
Sau khi làm việc với Foundry một chút, tôi rất thích trải nghiệm và muốn chia sẻ điều đó với những người khác. Do đó, bài báo này.
Bài viết này sẽ trình bày về các lợi ích của Foundry, quy trình cài đặt, phát triển NFT (vì mọi người đều quan tâm đến điều đó), thử nghiệm hợp đồng và triển khai nó với Figment Datahub .
Foundry là một bộ công cụ mô-đun, di động và nhanh chóng để phát triển ứng dụng Ethereum được viết bằng Rust.
Xưởng đúc được tạo thành từ ba thành phần:
Trọng tâm của ngày hôm nay sẽ là Forge. Nhưng tôi sẽ đăng các bài viết chuyên sâu về Caste và Anvil trong những tuần sắp tới.
Có rất nhiều công cụ phát triển hợp đồng thông minh như Truffle, Hardhat và Brownie. Nhưng một trong những lý do chính của tôi để xem xét Dapp Tools ngay từ đầu là các bài kiểm tra Solidity gốc. Viết hợp đồng thông minh không khó khi chuyển đổi giữa các framework như Hardhat và Brownie. Và chúng là những công cụ đáng kinh ngạc với các plugin, nhưng một người cần phải thông thạo JavaScript / TypeScript và Python để thực hiện thử nghiệm.
Foundry cho phép chúng tôi viết các bài kiểm tra của mình một cách nguyên bản trong Solidity. Điều này giúp tiết kiệm rất nhiều thời gian làm quen với các nhà phát triển mới và làm cho quá trình diễn ra suôn sẻ hơn. Theo kinh nghiệm của tôi về việc giúp mọi người điều hướng theo cách phát triển hợp đồng thông minh, tôi đã học được rằng cách tốt nhất và hiệu quả nhất để các nhà phát triển cơ sở tương tác với DAO / các dự án do cộng đồng duy trì là viết thử nghiệm và tìm hiểu về chính cơ sở mã. Tôi nhớ Scupy Tro People's từng đề cập rằng họ đã sử dụng cách tiếp cận tương tự khi phát triển Alchemix Finance trên Bankless .
Ngoài ra, tính năng fuzzing, mã gian lận, Cast và Anvil được tích hợp sẵn làm cho nó trở thành một bộ phần mềm vững chắc để thử nghiệm các hợp đồng thông minh. Sắp tới sẽ có các bài viết chi tiết hơn về các thành phần đó. [Dễ dàng tích hợp bộ phân tích tĩnh]
Hãy đi sâu vào và xây dựng một dự án NFT ngay bây giờ.
Nếu bạn đang sử dụng Mac hoặc Linux, tất cả những gì bạn cần làm là chạy hai lệnh:
curl -L https://foundry.paradigm.xyz | bash
foundryup
Đảm bảo đóng thiết bị đầu cuối trước khi chạy foundryup
.
Và Voila! Bạn đã làm xong.
Đối với Windows, bạn cần cài đặt Rust và sau đó:
cargo install --git https://github.com/foundry-rs/foundry --locked
Đối với bài viết này, chúng tôi sẽ tạo một dự án NFT đơn giản có tên là Figbots.
Bắt đầu bằng cách tạo một thư mục có tên "Figbots." Và chạy forge init
khi bạn ở trong thư mục. Lệnh này sẽ tạo một dự án đúc cho bạn với git
được khởi tạo.
Chúng ta hãy xem nhanh cấu trúc thư mục. Bạn có ba thư mục chính, đó là src, lib và test. Ở đây rất tự giải thích, bạn viết các hợp đồng của mình trong src
, các bài kiểm tra trong test
và lib
chứa tất cả các thư viện bạn đã cài đặt, ví dụ: OpenZeppelin. Ngoài ra, bạn nhận được foundry.toml
chứa tất cả các cấu hình giống như hardhat.config.js
và brownie-config.yaml
nếu bạn đã sử dụng các khung công tác đó. Một điều thú vị khác là .github, nơi bạn có thể viết các Hành động trên Github của mình. Tôi thấy nó thực sự hữu ích cho các bài kiểm tra khi làm việc nhóm.
Hãy bắt đầu xây dựng! Chúng tôi sẽ tạo một NFT đơn giản được gọi là Figbot với nguồn cung cấp hạn chế, chi phí (để đúc tiền) và rút tiền. Với cách tiếp cận này, chúng tôi có thể bao gồm các cạnh cho các thử nghiệm khác nhau. Trước hết, đổi tên Contract.sol
và test/Contract.t.sol
thành Figbot.sol
và Figbot.t.sol
tương ứng. Bây giờ, chúng ta không thể viết các hợp đồng thông minh mà không có Openzeppelin, phải không?
Cài đặt thư viện với Foundry hơi khác so với Hardhat và Brownie. Chúng tôi không có gói npm hoặc pip. Chúng tôi cài đặt thư viện trực tiếp từ Nguồn (GitHub repo) trong Foundry.
forge install Openzeppelin/openzeppelin-contracts
Bây giờ chúng tôi có thể nhập phần mở rộng ERC721URIStorage.sol để tạo NFT của chúng tôi. Để kiểm tra xem mọi thứ đều ổn chưa, chúng ta có thể chạy lệnh forge build
và nó sẽ biên dịch dự án của chúng ta. Trình biên dịch sẽ hét lên với bạn nếu có gì đó sai. Nếu không, bạn sẽ nhận được một biên dịch thành công.
Cũng giống như bất kỳ trình quản lý gói nào khác, Forge cho phép bạn sử dụng forge install <lib>,
forge remove <lib>
và forge update <lib>
để quản lý các phần phụ thuộc của mình.
Chúng tôi sẽ sử dụng ba hợp đồng từ Openzeppelin. Bộ đếm, ERC721 Lưu trữ và Có thể sở hữu. Đã đến lúc tải nội dung của chúng tôi lên IPFS bằng Pinata . Chúng tôi sử dụng hợp đồng Có thể sở hữu để đặt owner
địa chỉ triển khai và có quyền truy cập vào công cụ sửa đổi onlyOwner
để chỉ cho phép chủ sở hữu rút tiền. Counters
để giúp chúng tôi với (các) mã thông báo id và ERC721URIStorage
để giữ cho hợp đồng NFT đơn giản.
Đặt biến trạng thái:
MAX_SUPPLY
đến 100COST
thành 0,69 etherTOKEN_URI
tới CID, chúng tôi nhận được từ PinataSử dụng Bộ đếm cho id mã thông báo:
using Counters for Counters.Counter;
Counters.Counter private tokenIds;
Hàm tạo ERC721:
constructor() ERC721(“Figbot”, “FBT”) {}
Chức năng bạc hà:
msg.value
có lớn hơn COST
khôngtokenIds.current()
lớn hơn hoặc bằng MAX_SUPPLY
_safeMint
và _setTokenURI
Chức năng rút tiền:
function withdrawFunds() external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "No ether left to withdraw"); (bool success, ) = (msg.sender).call{value: balance}(""); require(success, "Withdrawal Failed"); emit Withdraw(msg.sender, balance); }
Chức năng TotalSupply:
function totalSupply() public view returns (uint256) { return _tokenIds.current(); }
Như chúng ta đã biết, việc kiểm tra các hợp đồng thông minh của chúng tôi thực sự quan trọng. Trong phần này, chúng ta sẽ viết một số bài kiểm tra để hiểu rõ hơn về forge test
và làm quen với việc viết bài kiểm tra ở dạng nguyên bản. Chúng tôi sẽ là ba mã gian lận Foundry (tôi thích chúng!) Để quản lý trạng thái tài khoản để phù hợp với kịch bản thử nghiệm của chúng tôi.
Chúng tôi sẽ thử nghiệm các tình huống sau:
Vì chúng ta có thể có logic phức tạp trong các hợp đồng thông minh của mình. Và chúng được mong đợi sẽ hoạt động khác nhau tùy thuộc vào trạng thái, tài khoản được sử dụng để gọi, thời gian, v.v. Để đối phó với các tình huống như vậy, chúng ta có thể sử dụng mã hóa để quản lý trạng thái của blockchain. Chúng ta có thể sử dụng các mã kiểm tra này bằng cách sử dụng vm
instance, là một phần của thư viện Foundry's Test
.
Chúng tôi sẽ sử dụng ba mã kiểm tra trong các thử nghiệm của mình:
startPrank
: Đặt msg.sender
cho tất cả các cuộc gọi tiếp theo cho đến khi stopPrank
được gọi.
stopPrank
:
Dừng một trò đùa đang hoạt động được bắt đầu bởi startPrank
, đặt lại msg.sender
và tx.origin
về các giá trị trước khi startPrank
được gọi.
deal
: Đặt số dư của một địa chỉ được cung cấp địa chỉ thành số dư nhất định.
Foundry đi kèm với một thư viện thử nghiệm tích hợp sẵn. Chúng tôi bắt đầu bằng cách nhập thư viện thử nghiệm này, hợp đồng của chúng tôi (thư mà chúng tôi muốn thử nghiệm), xác định thử nghiệm, thiết lập các biến và hàm setUp
.
pragma solidity ^0.8.13; import"forge-std/Test.sol"; import "../src/Figbot.sol"; contract FigbotTest is Test { Figbot figbot; address owner = address(0x1223); address alice = address(0x1889); address bob = address(0x1778); function setUp() public { vm.startPrank(owner); figbot = new Figbot(); vm.stopPrank(); } }
Đối với các biến trạng thái, chúng tôi tạo một hình Figbot
figbot
Đây cũng là nơi mà tôi muốn xác định tài khoản người dùng. Trong Foundry, bạn có thể mô tả địa chỉ bằng cách sử dụng address(0x1243)
. bạn có thể sử dụng bất kỳ bốn ký tự chữ và số nào cho việc này. Tôi đã tạo các tài khoản có tên chủ sở hữu, Alice và bob, tương ứng.
Bây giờ hàm setUp
của chúng ta. Đây là yêu cầu đối với các bài kiểm tra viết trong Foundry. Đây là nơi chúng tôi thực hiện tất cả các triển khai và những thứ có tính chất đó. Tôi đã sử dụng startPrank startPrank
để chuyển người dùng thành “chủ sở hữu”. Theo mặc định, Foundry sử dụng một địa chỉ cụ thể để triển khai các hợp đồng thử nghiệm. Nhưng điều đó làm cho việc kiểm tra các chức năng với các đặc quyền đặc biệt như withdrawFunds
trở nên khó khăn hơn. Do đó, chúng tôi chuyển sang tài khoản "chủ sở hữu" để triển khai này.
Bắt đầu với một bài kiểm tra khẳng định đơn giản để tìm hiểu quy ước Foundry. Theo quy ước, tất cả các chức năng kiểm tra phải có test
tiền tố. Và chúng tôi sử dụng khẳng định assertEq
để kiểm tra xem hai giá trị có bằng nhau hay không.
Chúng tôi gọi hàm MaxSupply
của mình và kiểm tra xem giá trị kết quả có là 100 hay không, như chúng tôi đã mô tả trong hợp đồng của mình. Và chúng tôi sử dụng forge test
để chạy thử nghiệm của mình.
Và Voila!!! chúng tôi có một bài kiểm tra đã vượt qua.
Bây giờ chúng ta đã viết một bài kiểm tra đơn giản, hãy viết một bài kiểm tra với mã hóa. Chức năng chính của hợp đồng của chúng tôi.
balanceOf
Nếu Alice là 1 Chúng tôi có một chức năng kiểm tra khác được sử dụng cho các bài kiểm tra mà chúng tôi dự kiến sẽ thất bại. Tiền tố được sử dụng cho một bài kiểm tra như vậy là testFail
. Chúng tôi sẽ kiểm tra xem chức năng mint
có hoạt động trở lại hay không nếu người gọi không có đủ tiền.
balanceOf
Bob là 1 Bởi vì bạc hà không đi qua, số dư của Bob sẽ không bằng 1. Do đó, nó sẽ thất bại, đó chính xác là những gì chúng tôi sử dụng testFail
. Vì vậy, khi bạn chạy forge test
, nó sẽ vượt qua.
Ở đây chúng tôi sẽ kiểm tra một chức năng mà chỉ "chủ sở hữu" mới có thể thực hiện thành công. Đối với thử nghiệm này, chúng tôi sẽ:
withdrawFunds
(nếu thành công, nó sẽ làm cho số dư của chủ sở hữu là 0,69 ether)Bây giờ chúng tôi đã thử nghiệm hợp đồng của mình, đã đến lúc triển khai nó. Chúng tôi cần khóa cá nhân cho một ví (với một số ETH thử nghiệm Rinkeby) và một URL RPC. Đối với URL RPC của chúng tôi, chúng tôi sẽ sử dụng Figment DataHu .
Figment DataHub cung cấp cho chúng tôi cơ sở hạ tầng để phát triển trên Web 3. Nó hỗ trợ nhiều chuỗi như Ethereum, Celo, Solana, Terra, v.v.
Bạn có thể lấy URL RPC của mình cho Rinkeby từ trong tab "Giao thức".
Mở thiết bị đầu cuối của bạn để nhập cả hai thứ này làm biến môi trường.
export FIG_RINKEBY_URL=<Your RPC endpoint> export PVT_KEY=<Your wallets private key>
Khi chúng ta có các biến môi trường, tất cả chúng ta đã sẵn sàng để triển khai
forge create Figbot --rpc-url=$FIG_RINKEBY_URL --private-key=$PVT_KEY
Chúng tôi gần như đã hoàn thành ở đây. Cho đến nay, chúng tôi đã viết, thử nghiệm và triển khai một hợp đồng thông minh với Foundry và Figment DataHub. Nhưng chúng ta vẫn chưa hoàn toàn xong. Bây giờ chúng tôi sẽ xác minh hợp đồng của chúng tôi. Chúng tôi sẽ cần thiết lập khóa API Etherscan của mình cho việc đó.
export ETHERSCAN_API=<Your Etherscan API Key>
Và bây giờ chúng tôi có thể xác minh hợp đồng thông minh của mình.
forge verify-contract --chain-id <Chain-Id> --num-of-optimizations 200 --compiler-version <Compiler Version> src/<Contract File>:<Contract> $ETHERSCAN_API
Xin chúc mừng! Giờ đây, bạn có thể viết, kiểm tra và triển khai các hợp đồng thông minh bằng Foundry. Tôi hy vọng bạn thích và học được từ bài viết này. Tôi thực sự thích viết này. Hãy cho tôi biết suy nghĩ của bạn về nó.