Hợp đồng thông minh là bất biến sau khi được triển khai trên blockchain, có nghĩa là chúng không thể sửa đổi được. Do đó, bất kỳ lỗi hoặc lỗ hổng bảo mật nào cũng có thể gây ra hậu quả nghiêm trọng, khiến việc thử nghiệm trở thành một bước không thể thiếu trong quá trình phát triển.
Trong bài học này, chúng ta sẽ thảo luận về hợp đồng Fa1_2TestFull
, bao gồm một loạt thử nghiệm được thiết kế để xác minh chức năng của hợp đồng mã thông báo của chúng tôi.
Fa1_2TestFull
Hợp đồng Fa1_2TestFull
là một lớp kế thừa tất cả các chức năng từ các hợp đồng khác nhau như Quản trị viên, Tạm dừng, Fa1_2, Mint, Burn và ChangeMetadata. Nó được sử dụng để tổng hợp tất cả các chức năng này và thực hiện kiểm tra kỹ lưỡng để đảm bảo hợp đồng hoạt động như mong đợi.
Lớp Python
Fa1_2TestFull(Quản trị viên, Tạm dừng, Fa1_2, Mint, Ghi, ChangeMetadata):
def __init__(self, quản trị viên, siêu dữ liệu, sổ cái, token_metadata):
ChangeMetadata.__init__(bản thân)
Đốt cháy.__init__(bản thân)
Cây bạc hà.__init__(bản thân)
Pháp1_2.__init__(bản thân, siêu dữ liệu, sổ cái, token_metadata)
Tạm dừng.__init__(bản thân)
Quản trị viên.__init__(bản thân, người quản lý)
Hàm tạo của lớp Fa1_2TestFull
khởi tạo tất cả các chức năng.
Đối với hợp đồng của chúng tôi, chúng tôi bắt đầu bằng cách thiết lập kịch bản thử nghiệm với các tài khoản thử nghiệm và khởi tạo hợp đồng. Việc này được thực hiện trong hàm kiểm tra được trang trí bằng @sp.add_test
.
Python
@sp.add_test(name="FA12")def test():
# Khởi tạo kịch bản và tài khoản thử nghiệm
sc = sp.test_scenario(m)
quản trị viên = sp.test_account("Quản trị viên")
alice = sp.test_account("Alice")
bob = sp.test_account("Robert")
# Khởi tạo hợp đồng với một số giá trị ban đầu
token_metadata = {
"decimals": sp.utils.bytes_of_string("18"), # Mandatory by the spec"name": sp.utils.bytes_of_string("My Great Token"), # Recommended"symbol": sp.utils.bytes_of_string("MGT"), # Recommended# Extra fields"icon": sp.utils.bytes_of_string("https://smartpy.io/static/img/logo-only.svg"),
}
hợp đồng_metadata = sp.utils.metadata_of_url("ipfs://QmaiAUj1FFNGYTu8rLBjc3eeN9cSKwaF8EGMBNDmhzPNFd")
c1 = m.Fa1_2TestFull(administrator=admin.address,metadata=contract_metadata,token_metadata=token_metadata,ledger={},)
sc += c1
Chúng tôi xác định các tài khoản thử nghiệm: Quản trị viên, Alice và Bob. Sau đó, chúng tôi khởi tạo hợp đồng của mình, Fa1_2TestFull
, với một số giá trị ban đầu. Toán tử +=
thêm hợp đồng vào kịch bản.
Từ giờ trở đi, để giúp bạn hiểu rõ hơn về mã, mã sẽ ở bên trái và hình ảnh trực quan của dòng mã được tô sáng sẽ ở bên phải. Ví dụ ở đây:
Bước tiếp theo là chạy thử nghiệm và điều này bao gồm việc kích hoạt các chức năng hợp đồng khác nhau và xác minh kết quả.
Ví dụ: để kiểm tra chức năng đúc, chúng tôi chạy:
Python
sc.h2("Quản trị viên đúc một vài đồng xu")
c1.mint(address=alice.address, value=12).run(sender=admin)
Dòng này chạy thử nghiệm trong đó quản trị viên đúc 12 mã thông báo cho Alice. Nếu chức năng đúc thành công mã thông báo và cập nhật chính xác số dư của Alice thì thử nghiệm này sẽ vượt qua.
SmartPy cung cấp phương thức verify
để đảm bảo rằng điều kiện là đúng. Nếu điều kiện không được đáp ứng, thử nghiệm sẽ thất bại. Ví dụ:
Python
c1.update_metadata(key="", value=sp.bytes("0x00")).run(sender=admin)
sc.verify(c1.data.metadata[""] == sp.byte("0x00"))
Những dòng đó xác minh rằng siêu dữ liệu của hợp đồng đã được cập nhật chính xác thành "0x00"
. Nếu nó không được cập nhật chính xác, thử nghiệm sẽ thất bại.
Các thử nghiệm hợp đồng thông minh của bạn phải bao gồm tất cả các trường hợp sử dụng có thể xảy ra, bao gồm cả các trường hợp khó khăn và các lỗi tiềm ẩn. Chúng có thể bao gồm chuyển khoản vượt quá số dư của người dùng, đốt mã thông báo khi hợp đồng bị tạm dừng, v.v.
Ví dụ: một bài kiểm tra chuyển giao không thành công có thể trông như thế này:
Python
sc.h2("Bob cố gắng chuyển từ Alice nhưng anh ấy không được cô ấy chấp thuận")
c1.transfer(from_=alice.address, to_=bob.địa chỉ, value=4).run(người gửi=bob, hợp lệ=Sai)
Tại đây, Bob cố gắng chuyển 4 token từ tài khoản của Alice mà không được sự chấp thuận. Vì thao tác này sẽ thất bại nên chúng tôi đặt valid=False
trong hàm run
. Nếu hợp đồng ngăn cản việc chuyển giao một cách chính xác, bài kiểm tra sẽ đạt.
Thử nghiệm là rất quan trọng trong việc phát triển hợp đồng thông minh. Do tính chất bất biến của blockchain, bất kỳ lỗi nào trong hợp đồng đều có thể gây ra hậu quả vĩnh viễn và có thể gây tốn kém. Viết các bài kiểm tra toàn diện đảm bảo rằng tất cả các chức năng hoạt động như mong đợi, dẫn đến các hợp đồng mạnh mẽ và an toàn.
Hãy nhớ viết bài kiểm tra cho cả trường hợp tích cực và tiêu cực. Các trường hợp tích cực xác nhận rằng một hàm hoạt động chính xác khi được sử dụng như dự định. Các trường hợp tiêu cực đảm bảo hợp đồng hoạt động chính xác trong việc xử lý các đầu vào không chính xác hoặc không mong muốn.
Hợp đồng thông minh là bất biến sau khi được triển khai trên blockchain, có nghĩa là chúng không thể sửa đổi được. Do đó, bất kỳ lỗi hoặc lỗ hổng bảo mật nào cũng có thể gây ra hậu quả nghiêm trọng, khiến việc thử nghiệm trở thành một bước không thể thiếu trong quá trình phát triển.
Trong bài học này, chúng ta sẽ thảo luận về hợp đồng Fa1_2TestFull
, bao gồm một loạt thử nghiệm được thiết kế để xác minh chức năng của hợp đồng mã thông báo của chúng tôi.
Fa1_2TestFull
Hợp đồng Fa1_2TestFull
là một lớp kế thừa tất cả các chức năng từ các hợp đồng khác nhau như Quản trị viên, Tạm dừng, Fa1_2, Mint, Burn và ChangeMetadata. Nó được sử dụng để tổng hợp tất cả các chức năng này và thực hiện kiểm tra kỹ lưỡng để đảm bảo hợp đồng hoạt động như mong đợi.
Lớp Python
Fa1_2TestFull(Quản trị viên, Tạm dừng, Fa1_2, Mint, Ghi, ChangeMetadata):
def __init__(self, quản trị viên, siêu dữ liệu, sổ cái, token_metadata):
ChangeMetadata.__init__(bản thân)
Đốt cháy.__init__(bản thân)
Cây bạc hà.__init__(bản thân)
Pháp1_2.__init__(bản thân, siêu dữ liệu, sổ cái, token_metadata)
Tạm dừng.__init__(bản thân)
Quản trị viên.__init__(bản thân, người quản lý)
Hàm tạo của lớp Fa1_2TestFull
khởi tạo tất cả các chức năng.
Đối với hợp đồng của chúng tôi, chúng tôi bắt đầu bằng cách thiết lập kịch bản thử nghiệm với các tài khoản thử nghiệm và khởi tạo hợp đồng. Việc này được thực hiện trong hàm kiểm tra được trang trí bằng @sp.add_test
.
Python
@sp.add_test(name="FA12")def test():
# Khởi tạo kịch bản và tài khoản thử nghiệm
sc = sp.test_scenario(m)
quản trị viên = sp.test_account("Quản trị viên")
alice = sp.test_account("Alice")
bob = sp.test_account("Robert")
# Khởi tạo hợp đồng với một số giá trị ban đầu
token_metadata = {
"decimals": sp.utils.bytes_of_string("18"), # Mandatory by the spec"name": sp.utils.bytes_of_string("My Great Token"), # Recommended"symbol": sp.utils.bytes_of_string("MGT"), # Recommended# Extra fields"icon": sp.utils.bytes_of_string("https://smartpy.io/static/img/logo-only.svg"),
}
hợp đồng_metadata = sp.utils.metadata_of_url("ipfs://QmaiAUj1FFNGYTu8rLBjc3eeN9cSKwaF8EGMBNDmhzPNFd")
c1 = m.Fa1_2TestFull(administrator=admin.address,metadata=contract_metadata,token_metadata=token_metadata,ledger={},)
sc += c1
Chúng tôi xác định các tài khoản thử nghiệm: Quản trị viên, Alice và Bob. Sau đó, chúng tôi khởi tạo hợp đồng của mình, Fa1_2TestFull
, với một số giá trị ban đầu. Toán tử +=
thêm hợp đồng vào kịch bản.
Từ giờ trở đi, để giúp bạn hiểu rõ hơn về mã, mã sẽ ở bên trái và hình ảnh trực quan của dòng mã được tô sáng sẽ ở bên phải. Ví dụ ở đây:
Bước tiếp theo là chạy thử nghiệm và điều này bao gồm việc kích hoạt các chức năng hợp đồng khác nhau và xác minh kết quả.
Ví dụ: để kiểm tra chức năng đúc, chúng tôi chạy:
Python
sc.h2("Quản trị viên đúc một vài đồng xu")
c1.mint(address=alice.address, value=12).run(sender=admin)
Dòng này chạy thử nghiệm trong đó quản trị viên đúc 12 mã thông báo cho Alice. Nếu chức năng đúc thành công mã thông báo và cập nhật chính xác số dư của Alice thì thử nghiệm này sẽ vượt qua.
SmartPy cung cấp phương thức verify
để đảm bảo rằng điều kiện là đúng. Nếu điều kiện không được đáp ứng, thử nghiệm sẽ thất bại. Ví dụ:
Python
c1.update_metadata(key="", value=sp.bytes("0x00")).run(sender=admin)
sc.verify(c1.data.metadata[""] == sp.byte("0x00"))
Những dòng đó xác minh rằng siêu dữ liệu của hợp đồng đã được cập nhật chính xác thành "0x00"
. Nếu nó không được cập nhật chính xác, thử nghiệm sẽ thất bại.
Các thử nghiệm hợp đồng thông minh của bạn phải bao gồm tất cả các trường hợp sử dụng có thể xảy ra, bao gồm cả các trường hợp khó khăn và các lỗi tiềm ẩn. Chúng có thể bao gồm chuyển khoản vượt quá số dư của người dùng, đốt mã thông báo khi hợp đồng bị tạm dừng, v.v.
Ví dụ: một bài kiểm tra chuyển giao không thành công có thể trông như thế này:
Python
sc.h2("Bob cố gắng chuyển từ Alice nhưng anh ấy không được cô ấy chấp thuận")
c1.transfer(from_=alice.address, to_=bob.địa chỉ, value=4).run(người gửi=bob, hợp lệ=Sai)
Tại đây, Bob cố gắng chuyển 4 token từ tài khoản của Alice mà không được sự chấp thuận. Vì thao tác này sẽ thất bại nên chúng tôi đặt valid=False
trong hàm run
. Nếu hợp đồng ngăn cản việc chuyển giao một cách chính xác, bài kiểm tra sẽ đạt.
Thử nghiệm là rất quan trọng trong việc phát triển hợp đồng thông minh. Do tính chất bất biến của blockchain, bất kỳ lỗi nào trong hợp đồng đều có thể gây ra hậu quả vĩnh viễn và có thể gây tốn kém. Viết các bài kiểm tra toàn diện đảm bảo rằng tất cả các chức năng hoạt động như mong đợi, dẫn đến các hợp đồng mạnh mẽ và an toàn.
Hãy nhớ viết bài kiểm tra cho cả trường hợp tích cực và tiêu cực. Các trường hợp tích cực xác nhận rằng một hàm hoạt động chính xác khi được sử dụng như dự định. Các trường hợp tiêu cực đảm bảo hợp đồng hoạt động chính xác trong việc xử lý các đầu vào không chính xác hoặc không mong muốn.