English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french

简体中文 繁體中文 English 日本語 Deutsch 한국 사람 بالعربية TÜRKÇE คนไทย Français русский

回答

收藏

4.4 存款/提款逻辑测试

开源社区 开源社区 8493 人阅读 | 0 人回复 | 2025-03-08

在本课中,我们将编写一些有趣的测试。
首先,我们要更新之前编写的合约的初始化过程,因为我们引入了一个新变量,它应该存储在 c4 存储器中。
如果您现在尝试运行我们的测试 - yarn test 您可以看到测试将失败。您还将看到发生在我们合约上的交易跟踪,其中一个交易的错误代码为 9. Have a look at the exit codes documentation.
9 - Cell下溢。从片断基元读取数据时,试图读取的位或引用数超过总数。
更新我们的合约包装器
首先,让我们更新我们的合约包装器,以便它能意识到 c4 存储中的第三个参数。也就是说,我们将更新 MainContractConfig 和 mainContractConfigToCell 函数
  1. // ...library imports/ o7 z8 F. k6 [8 p& q5 O1 K& x5 B

  2. 0 C4 N1 I5 Q+ E! c, h8 q
  3. export type MainContractConfig = {
    ; A" w( w$ P2 d# s! x2 O, A0 s3 k
  4.   number: number;) z6 e7 c( H/ o9 _! h0 U
  5.   address: Address;6 }- {3 e  ]' k" t) o% l, K
  6.   owner_address: Address;
    * S6 ~$ f5 C" W2 ^$ `+ J( {5 ?
  7. };( o  m; B0 a7 k
  8.   P& [; e6 u0 h! D  a, b
  9. export function mainContractConfigToCell(config: MainContractConfig): Cell {
    ' b# A. H5 Z( R: j, h
  10.   return beginCell()4 q& }; O6 H, d
  11.     .storeUint(config.number, 32)
    % w7 u8 W$ t  m
  12.     .storeAddress(config.address)# p( y' q. d  j% L0 d
  13.     .storeAddress(config.owner_address)
    : K, X: P# F0 K  p: A. M
  14.     .endCell();) B5 O" g: }$ n- H9 m2 B: K
  15. }
    ( @+ ?1 v% Q, C2 o

  16. 5 c9 P  p- J* |" h+ h  I$ q
  17. // ...contact wrapper class
复制代码
封装文件中还有一点需要更新-getData 方法,这样它也会返回 owner_address 我们还将创建新方法 getBalance,以测试存款后余额是否增加:

6 h& u. }& W* S+ H5 M
  1. async getData(provider: ContractProvider) {
    4 M4 N' x3 ?8 s/ s  y2 l9 Q' z2 s
  2.     const { stack } = await provider.get("get_contract_storage_data", []);
    , M9 \6 U9 Y+ j* b" Q; r2 m+ W" f! D  K
  3.     return {
    + B. C" X3 S" a* D4 J1 d
  4.       number: stack.readNumber(),  _9 Q9 q7 i3 K
  5.       recent_sender: stack.readAddress(),0 I# F: @! _: M3 B, u1 P- T. ]: a
  6.       owner_address: stack.readAddress(),
    + M) y2 m( y/ i/ j; d
  7.     };
    ; O' ]6 V' J- `4 Y% j
  8.   }2 J" A% _' ~/ l8 |$ h: T& F
  9.   
    9 @1 w! h1 M# M# H% `9 p
  10. async getBalance(provider: ContractProvider) {) B7 n1 b; J) k' B1 R, \8 E/ f( d
  11.     const { stack } = await provider.get("balance", []);
    % ?4 I( w, J; p9 E$ ^9 W6 u# {
  12.     return {# Z3 L2 G; N& ?% H. ]4 _/ ~
  13.       number: stack.readNumber(),
    & W7 h: w. X. g, {' I- C  u
  14.     };
    7 X1 B, L* u0 D
  15. }
复制代码
  1. // ...library imports, m. f. O6 ~( S! S* k! c
  2. * E: g1 ^/ m( T8 N; L7 L' |- m
  3. describe("main.fc contract tests", () => {# H: x! T; W+ X2 e
  4.   it("should get the proper most recent sender address", async () => {
    6 _* y7 H0 R% n2 X
  5.     const blockchain = await Blockchain.create();
    $ L* F1 x  |. o0 }
  6.     const codeCell = Cell.fromBoc(Buffer.from(hex, "hex"))[0];
    2 B! }- p) v1 k( z
  7. $ n8 p, _% C( K. g: Z% F
  8.     const initAddress = await blockchain.treasury("initAddress");" Q2 w) Q! P' z5 [, d
  9.     const ownerAddress = await blockchain.treasury("ownerAddress");
    1 D1 Q$ x9 n4 L4 w& ~5 b# c& ?: i7 k
  10.    
    4 f/ z1 Y. K# {, C. ?3 k8 t; Z
  11.     const myContract = blockchain.openContract(
    4 ]$ l; J5 i3 R' y- @
  12.       await MainContract.createFromConfig(; j/ X; \3 R/ @- g4 R
  13.         {! `( N2 e/ p; c! b: H# E
  14.           number: 0,
      J0 U8 ~. x& Y+ i; j
  15.           address: initAddress.address,/ V- U' c# l$ H6 \& j' u( H8 G
  16.           owner_address: ownerAddress.address, // now we create myContract from 3 parameters
    9 E8 P! n* s8 k. ]8 L1 O: S7 R& s
  17.         },5 @5 W1 k* J) z* ?* b* Q- P
  18.         codeCell( I" {9 P. P: w# }4 Q
  19.       )
    ! v0 U" z; T6 r+ e
  20.     );/ [/ x# R8 f, a7 {; M2 }/ f

  21. 4 j* b# c3 W* V8 t  G. ?
  22. // ...rest of testing code
复制代码

0 ^9 [& }0 N% U, S& d
我们引入一个新的金库,它实际上将是合约的所有者,只有这个所有者以后才能提取资金。这些更新在 tests/main.spec.ts 中进行:
  1. // ...library imports
    1 T& o2 ~6 [  k4 U' d9 C; P1 s( X

  2. # Q  l4 x, [- M8 x* G) V- |- g7 x
  3. describe("main.fc contract tests", () => {
    9 y% U. t, V" Z# [( |2 e5 f' u
  4.   it("should get the proper most recent sender address", async () => {8 j7 Y% g4 K$ K! `, ~, m) n
  5.     const blockchain = await Blockchain.create();
    ; h, [# u( m, M7 X9 O6 A. [
  6.     const codeCell = Cell.fromBoc(Buffer.from(hex, "hex"))[0];
    % b* s9 R! Z. r2 ?
  7. / ^% C0 m$ i; Y, Q& a
  8.     const initAddress = await blockchain.treasury("initAddress");
    8 D, P4 v  |. t* |
  9.     const ownerAddress = await blockchain.treasury("ownerAddress");2 R6 m( N4 G6 Z5 k) t4 \, G
  10.     - X, D( S' w+ }' k. ~4 ~: R
  11.     const myContract = blockchain.openContract(
    3 P) r2 O3 {5 _% I( C7 _6 C) O% Y
  12.       await MainContract.createFromConfig(
    6 M$ s" {2 ?* g
  13.         {
    5 `* [8 E' w* U5 N' {1 q6 E6 T9 i
  14.           number: 0,
    # _- h1 Y- o7 L% C0 p: Z' N3 [, m
  15.           address: initAddress.address,/ D8 n4 Y- d  F: r+ l' F
  16.           owner_address: ownerAddress.address, // now we create myContract from 3 parameters) l4 y; e' b9 ~6 g, ]
  17.         },7 ~' M  G" b% S7 M
  18.         codeCell) v9 y0 u0 V1 Y' l
  19.       )
    : H  ~% r- j+ b5 i! j8 l
  20.     );; l* j8 Z! U1 d- Z# ^2 Z  B, V* |

  21. 0 {! Q  e6 ?( C5 c' d( i% `( ]
  22. // ...rest of testing code
复制代码
现在我们好了。 yarn test 成功通过我们之前编写的测试。

9 d: w5 O2 M7 @存款测试
让我们在 main.spec.ts 文件中再添加几个测试。
由于我们必须在每次新测试前重新启动合约,因此我们还将把合约启动引入 Jest 的 beforeEach 函数:
  1. // We need to additionally import SandboxContract and TreasuryContract
    7 j7 Y0 f% [9 `4 `0 a1 J" X& B5 i4 M
  2. import { Blockchain, SandboxContract, TreasuryContract } from "@ton/sandbox";
    6 p7 G/ }: A' n! J
  3. // ... other library imports: @. k" g8 Z3 c- N1 y) ^& ~
  4. describe("main.fc contract tests", () => {# X; Z! Z" W4 q7 p7 Q: j
  5.   let blockchain: Blockchain;
    0 B0 u# J; V' N# Q3 G
  6.   let myContract: SandboxContract<MainContract>;* J; z' v( V8 g# O4 v9 }' `7 `
  7.   let initWallet: SandboxContract<TreasuryContract>;0 V5 p6 {; p! y* U8 o
  8.   let ownerWallet: SandboxContract<TreasuryContract>;
    ' {' O, r" B! Q/ z' F
  9. ) V9 _! `/ T* _9 l1 {
  10.   beforeEach(async () => {
    , E- l* L1 y) r! I/ e& X+ G* J
  11.     blockchain = await Blockchain.create();
    ' b) h& B" p2 l: [
  12.     initWallet = await blockchain.treasury("initWallet");5 s- z/ v, E3 x8 H2 l
  13.     ownerWallet = await blockchain.treasury("ownerWallet");
    ' Y. C0 ]5 \. Q" m

  14. ; M2 ?0 Q/ }7 G+ A+ f( F) {% L
  15.     const codeCell = Cell.fromBoc(Buffer.from(hex, "hex"))[0];$ @1 B! l$ c, l( j- X
  16. ; p- M, F0 U% Y" o7 C: C
  17.     myContract = blockchain.openContract(8 H/ |* Y9 m* l2 S* c
  18.       await MainContract.createFromConfig(7 }0 R, G- i/ K9 s
  19.         {, V$ t" W) a% z' y
  20.           number: 0,
    ' D3 I! y. f5 C( ^3 |! q
  21.           address: initWallet.address,
    / m* s2 S# T$ @4 Z
  22.           owner_address: ownerWallet.address,
    / y- r. m* G0 w
  23.         },# \( R% p" [  M# M4 G6 ]
  24.         codeCell4 R& L. X& ~0 l: T$ I# [1 k  k
  25.       )6 }5 N2 y" N( E  U4 E+ M
  26.     );9 Z( a/ f# }7 \* T# ^; [
  27.   });
    * X% I. @- R3 ?: X% E0 d) O9 [

  28. ' l# Q- w: i) u: k0 }, G
  29.   it("should get the proper most recent sender address", async () => {$ v0 [6 P" J$ h
  30.     const senderWallet = await blockchain.treasury("sender");
    5 \/ u  W. y! @! K; E- L. V1 t9 V
  31. # W7 ]5 j0 ^) [& U5 H6 L8 K: O$ C" C
  32.     const sentMessageResult = await myContract.sendIncrement(
    . o1 B" ~! Z. I" P7 A2 z% v
  33.       senderWallet.getSender(),6 h& u$ J. ]! N2 k
  34.       toNano("0.05"),
    , K" c2 {  T: ~, G% P5 R
  35.       1
    ) T% L5 v( i8 e% i/ E
  36.     );
    , g$ o. z$ T' p* \( i0 q

  37. ! k9 m$ O1 K, z& }/ p( F  k
  38.     expect(sentMessageResult.transactions).toHaveTransaction({8 N6 K, I, N/ J3 F$ k
  39.       from: senderWallet.address,
    2 w, x& s; m$ P( A! x$ p8 T# X3 j2 D
  40.       to: myContract.address,$ [- n, T% h; q% S4 J( b
  41.       success: true,* s, S; b3 `' r
  42.     });' O3 U0 k) y+ B( \

  43. , j: Z! F1 y) m' o5 i, W7 v! t3 Q
  44.     const data = await myContract.getData();. O6 [( u1 a: `; V: J7 a
  45. * m  _- \* L8 t2 U! O
  46.     expect(data.recent_sender.toString()).toBe(senderWallet.address.toString());
    ; h5 H  }9 j) M: h4 G8 G9 x( D2 d2 ~
  47.     expect(data.number).toEqual(1);$ h2 }- c/ }+ q* R/ @3 [
  48.   });
    4 s. ]0 n) _( e+ U  p  V+ |
  49.   it("successfully deposits funds", () => {
    $ C2 [  D6 k; F8 K5 [' C% `1 ]
  50.     // test logic is coming
    1 q8 P  B0 E! D$ L
  51.   });
    ) e- e- U! i% N; ]) n# J
  52.   it("should return deposit funds as no command is sent", () => {
    4 P/ w! c$ h: _8 c3 W5 r+ J
  53.     // test logic is coming; O+ Z! e; }7 _% n
  54.   });8 _& L# f0 ]4 P! l& y! V
  55.   it("successfully withdraws funds on behalf of owner", () => {
    & k% I2 E% V# w5 ?5 o
  56.     // test logic is coming! W2 h6 y$ o. E
  57.   });
    ; J6 {7 P* D5 O" P) O& h: L" L
  58.   it("fails to withdraw funds on behalf of non-owner", () => {
    & b) k3 O9 |; `" X, q  d. k% U+ F
  59.     // test logic is coming8 b! d, P8 A  t( p) u; E" C# J
  60.   });
    ) P$ P% J! p" ]) y
  61.   it("fails to withdraw funds because lack of balance", () => {/ W+ n0 i$ d* e* C
  62.     // test logic is coming
    ) {0 @; [) F9 ^$ A
  63.   });
    # I/ P( K; V& {+ Y% Y( j$ z9 c* @" J
  64. });
复制代码
我们只是将第一个测试的部分行移动到了 beforeEach 中,其余的行应留在第一个测试中 it
让我们为存款写一个测试。我们将发送一条 op == 2 的信息,然后检查余额。像往常一样,首先创建一个封装方法,我们将其称为 sendDeposit:
  1. async sendDeposit(provider: ContractProvider, sender: Sender, value: bigint) {( Q4 @4 k, C3 L2 c! B/ q/ G) V/ m
  2.     const msg_body = beginCell(): B* L% S7 S$ C+ j7 Q9 j8 [) V
  3.       .storeUint(2, 32) // OP code
    6 l) M- f' d( V# C0 ^' {. Z
  4.       .endCell();
    # A- z( g3 N7 @1 _; D

  5. * {# t: q- p! v
  6.     await provider.internal(sender, {
    ' {0 J- j. K' g. A
  7.       value,% Q# r2 T4 m( F9 z; m0 Q/ w) J) U. E. k
  8.       sendMode: SendMode.PAY_GAS_SEPARATELY,
    # \. A' N9 `5 \1 O' e- L
  9.       body: msg_body,
    # M9 I4 u; z# r7 T" M5 j
  10.     });, i6 Q" ~1 @8 a) [
  11.   }
复制代码
我们将不详细介绍这种方法,因为它非常简单--我们只需在信息正文中传递一个操作码。
下面是我们如何使用该方法运行存款测试。
  1. it("successfully deposits funds", async () => {
    ; a2 d- w: d" ?  U; }% N# D
  2.     const senderWallet = await blockchain.treasury("sender");- ^8 \* G3 ^4 P

  3. # f% S5 w! D1 ?9 I8 f
  4.     const depositMessageResult = await myContract.sendDeposit(: H# M4 ^( D( i& R
  5.       senderWallet.getSender(),
    7 V5 C$ H6 {/ C, \+ L
  6.       toNano("5")3 \0 [% u9 o, G. y; d: w
  7.     );# Y4 P% j; P1 ~3 d! R7 ]5 P4 ~2 g

  8. 3 a1 G; Q9 A9 d! z& z
  9.     expect(depositMessageResult.transactions).toHaveTransaction({3 K* ^5 w1 D. N- p" Y
  10.       from: senderWallet.address,
    ; j* J2 w9 o( V! ^! g4 d* h7 k
  11.       to: myContract.address,' H, \! C: L+ g' [8 O: t
  12.       success: true,
    ! e5 `, a; Z% A( B( j1 M& S' Q) }
  13.     });1 y3 _3 i* k! o

  14. : l7 j7 B9 p. v, _3 [% ]" R. J& o
  15.     const balanceRequest = await myContract.getBalance();$ ?* z1 Q) Y) G
  16. : ^. v" Z; s5 |) y; ]
  17.     expect(balanceRequest.number).toBeGreaterThan(toNano("4.99"));
    4 e  \4 j2 T0 E% O) H) ]/ z2 M9 n- a
  18.   });
复制代码
请注意我们是如何检查合约余额是否大于 4.99 TON的,因为我们知道手续费会损失一些资金。
我们再写一个存款测试,但这次会出现误报。我们将在没有存款操作码的情况下发送资金,并期待返回交易,因为该操作码未知。
和以往一样,我们还有一个包装器:
  1. async sendNoCodeDeposit(
    $ Y0 |; L2 M; t* ^, Z1 D
  2.     provider: ContractProvider,( s# f4 G% z4 S8 ^4 v
  3.     sender: Sender,4 s; I9 _2 X* S, T/ i& m9 _$ }/ a
  4.     value: bigint  |4 W9 F) ^' D
  5.   ) {
    : G! w3 e- {5 B% d5 n6 P
  6.     const msg_body = beginCell().endCell();
    3 Y5 \) L/ j8 F* p# K

  7. ' @1 x8 s! q2 X' {* B8 ?$ W* ~
  8.     await provider.internal(sender, {* z( N$ p3 P$ V
  9.       value,
    $ u7 c- W4 C+ T1 t( b* C  h
  10.       sendMode: SendMode.PAY_GAS_SEPARATELY,8 H) _5 {( ~  h6 p/ ]
  11.       body: msg_body,. l* A% o7 Y  G# s8 C
  12.     });
    3 X  s  e& T, l- z4 S3 J/ K
  13.   }
复制代码
下面是测试代码:

) C/ {  j) [& Q/ `2 @! b' C
  1. it("should return funds as no command is sent", async () => {
    7 R, W  O; m, k  n( h# H
  2.     const senderWallet = await blockchain.treasury("sender");
    ; h; v/ x. o; j
  3. ' c/ D# j1 P4 E) w
  4.     const depositMessageResult = await myContract.sendNoCodeDeposit(4 N1 E% @- O, _: d6 i# l
  5.       senderWallet.getSender(),6 ^6 j  T# N* d  V- M  U8 x
  6.       toNano("5")/ m- k! O$ W, a# P. h$ f
  7.     );3 p. N9 b4 X) h0 B  ]  t

  8. 3 w& ^& q. I/ i0 D$ e$ E  ^4 q
  9.     expect(depositMessageResult.transactions).toHaveTransaction({
    $ |; Q+ ]. x& I9 [3 G
  10.       from: myContract.address,
    6 h6 ]& z4 i+ Y
  11.       to: senderWallet.address,
    + a' ?0 P" g9 }+ L
  12.       success: true,
    ! e8 |+ ?/ |- B; V
  13.     });
    3 g* |5 B" P& Q! ^0 k" e% N5 }3 S# D

  14. $ l7 _/ m  a- p; P1 n
  15.     const balanceRequest = await myContract.getBalance();  V' ~' ?' `4 O$ M3 E

  16. $ L3 c  `. s+ ]- A5 M
  17.     expect(balanceRequest.number).toBe(0);/ K0 b, P  [& [9 `
  18. });
复制代码
提款测试
让我们先创建一个用于提款的新包装器:
  1. async sendWithdrawalRequest(& c1 R  Y$ `* q& k5 y
  2.     provider: ContractProvider,
    0 D. R8 t$ T# d" W% q5 ]
  3.     sender: Sender,0 k5 I- x) _2 W$ C" Z
  4.     value: bigint,; l% i, x/ \7 l$ c4 ~
  5.     amount: bigint
    . V$ G, v. g) g
  6.   ) {" P8 T: P8 g  N% D
  7.     const msg_body = beginCell()
    $ Y& I- j; v9 {5 I5 u2 n# J% ^- \
  8.       .storeUint(3, 32) // OP code8 ]+ r- ]/ @8 K& e+ o
  9.       .storeCoins(amount)
    4 @' G" T1 i6 `8 T
  10.       .endCell();! ]7 |$ a0 j5 H

  11. $ A2 F" h3 P; w4 O& C* n
  12.     await provider.internal(sender, {
    ; A" v4 m9 V9 O5 h# ], |( f! A& L
  13.       value,
    2 B/ E5 n5 |% I' J0 j5 Y+ @
  14.       sendMode: SendMode.PAY_GAS_SEPARATELY,4 b4 c& M" r4 R+ t& a  A
  15.       body: msg_body,4 {$ g! o8 `& p* d" R! H6 C4 L# U: W
  16.     });
    , q; ^3 K" G; u; S) ]9 e# J1 ~
  17.   }
复制代码
我们输入适当的 msg_body 和所需的提款 amount 。
我们将进行 3 项不同的测试。让我们一起来看看:
  1. it("successfully withdraws funds on behalf of owner", async () => {1 p  \) Y1 [# `& p# `7 E" F: t! e* S% q
  2.     const senderWallet = await blockchain.treasury("sender");
      Z3 J3 L+ ^2 X) m

  3. 3 h5 Q9 s. m! B$ k7 }) f' n
  4.     await myContract.sendDeposit(senderWallet.getSender(), toNano("5"));  T  b; j$ @- u5 x- d+ q
  5. 9 a0 h% j4 W8 k1 ^
  6.     const withdrawalRequestResult = await myContract.sendWithdrawalRequest(
    3 P/ F9 a% p4 j- }7 ~7 z
  7.       ownerWallet.getSender(),% _) n" N2 k  Y: Q# r
  8.       toNano("0.05"),
    / S  g8 n0 F( k2 Z+ t. G( ?
  9.       toNano("1")* A" W" Q/ e9 H5 f, q
  10.     );: O9 C' y) h. v* W* y9 e' r5 {2 U

  11. $ p2 Y1 ^% W! s6 A
  12.     expect(withdrawalRequestResult.transactions).toHaveTransaction({- h; ]7 q% e$ D8 @. d+ _$ o. M
  13.       from: myContract.address,2 Y* M. L7 O/ q$ i
  14.       to: ownerWallet.address,
    + P' J9 x9 U5 u$ J# N0 ^
  15.       success: true,8 c! ^9 l( y) w" I$ F
  16.       value: toNano(1),' L8 M) G5 c" `. i: K; m3 ?
  17.     });
    4 _/ D) B2 D. c% V& C. ?
  18.   });
复制代码
要成功提款,我们首先要正确存款。然后我们调用 sendWithdrawalRequest 指定我们要提取 1 Ton。请注意,0.05 Ton只是为了支付费用而指定的信息值。
( u. Q7 J* W. E/ [, Z6 o) T
  1. it("fails to withdraw funds on behalf of not-owner", async () => {# j0 J3 w" v1 l. Q! I7 a
  2.     const senderWallet = await blockchain.treasury("sender");
    3 z, [2 P: l9 N& O$ ?9 r
  3. ( @: f! K0 M( E
  4.     await myContract.sendDeposit(senderWallet.getSender(), toNano("5"));
    * B9 Y$ x8 r  t/ }' b% O. B2 F
  5. ; u- O$ ?: Q: \# |, j5 Z) E
  6.     const withdrawalRequestResult = await myContract.sendWithdrawalRequest(( B. f5 ~/ N: N% e) G
  7.       senderWallet.getSender(),& i8 \3 s  l9 V8 a2 e$ n
  8.       toNano("0.5"),
      D/ l4 h6 Q. K6 @: m( S' B  Y* c
  9.       toNano("1")" w! a6 ?% L9 ]% ]1 J
  10.     );7 z2 M) _9 Y8 ~! y# P

  11. , j0 ]- d- j' m2 R8 W2 m+ N4 [1 y, U
  12.     expect(withdrawalRequestResult.transactions).toHaveTransaction({( ?. C! R8 F5 g. y5 ?% I) Y
  13.       from: senderWallet.address,
    " k7 h' W5 f0 o* B. J
  14.       to: myContract.address,
    1 a1 u" z6 K3 P1 u0 D: y  P
  15.       success: false,
    6 k! R& j# @0 f# u. I9 v: o& K7 {! J
  16.       exitCode: 103,
    2 f( q% T6 ^3 N# ]
  17.     });, s1 i& H5 i+ T" K! j( ~* ]
  18.   });
复制代码
在本次测试中,我们代表发送方钱包而不是所有者钱包发送提款请求(两者的区别在于初始化时我们提供的助记词).
还请注意,我们是如何通过 success: false 和具体的失败原因 exitCode: 103. 为了确保我们做得正确,请看一下我们的合约代码,我们有这样一行代码:
  1. throw_unless(103, equal_slice_bits(sender_address, owner_address));5 Q* X9 f: u7 S( W  i: @& J
复制代码
我们进行最后一项测试--由于没有余额,提款失败:
  1. it("fails to withdraw funds because lack of balance", async () => {
    4 \( J, W* L" Z+ _0 g' G' E
  2.     const withdrawalRequestResult = await myContract.sendWithdrawalRequest(
    : ^& `9 q5 a$ T: I, n
  3.       ownerWallet.getSender(),
    7 v" I+ Q2 f* W9 V
  4.       toNano("0.5"),' L; Z& b8 M( M& F2 F$ e! P
  5.       toNano("1")
    ; Y; x+ {5 y; h# d8 `. N+ U
  6.     );  B, u* E  T1 A6 _
  7. 6 K. \. ?' {# e2 @6 G
  8.     expect(withdrawalRequestResult.transactions).toHaveTransaction({
    + A, s" h! q3 J- P9 s3 Q2 c! s
  9.       from: ownerWallet.address,/ T5 _' F( E5 |0 X
  10.       to: myContract.address,
    % f$ l" f3 n( E' _) s9 ?; m
  11.       success: false,7 X& }9 G' Q4 p' s: z4 Y
  12.       exitCode: 104,- s- I! Q1 h% s% ]0 }: `& n7 K
  13.     });( J+ D9 z6 }; A  P, i) m  g
  14.   });
复制代码
  1. throw_unless(104, balance >= withdraw_amount);
    ) D' w  _# g5 n% u% R2 _2 w" M
复制代码
就是这样
几章之后,我们将学习如何构建网络客户端,以便与合约进行交互。
" s5 ]2 G; b: _/ a( N

% Y, c% O7 e4 d# _) w: z
分享到:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则