Open dfstio opened 9 months ago
If method1, accessing token account A, calls method2, accessing token account B, the get function gives 0 for the balance of token account B even though the balance is not 0:
● MinaNFT contract › escrow should transfer NFT and funds
Field.assertEquals(): 0 != 1000000000
96 | const account = Account(address, this.token.id);
97 | const tokenBalance = account.balance.getAndAssertEquals();
> 98 | tokenBalance.assertEquals(UInt64.from(1_000_000_000));
| ^
99 | }
at _Field.assertEquals (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:4671:17)
at assertEqualImplicit (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:6466:12)
at Object.assertEqual (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:6456:12)
at _UInt64.assertEquals (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:7132:14)
at MinaNFTNameServiceContract.isNFT (src/contract/names.ts:98:18)
at MinaNFTNameServiceContract.transfer (src/contract/names.ts:199:10)
at runCalledContract (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:14514:29)
at .yarn/cache/o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:6440:21
at run_prover (src/lib/snarky/src/base/snark0.ml:1150:17)
at run$3 (src/lib/snarky/src/base/as_prover0.ml:15:17)
at run$4 (src/lib/snarky/src/base/as_prover0.ml:74:18)
at ../../../../../../workspace_root/src/lib/snarky/src/base/checked_runner.ml:260:15
at ../../../../../../workspace_root/src/lib/snarky/src/base/checked_runner.ml:54:30
at exists (src/lib/snarky/src/base/snark0.ml:1213:11)
at exists$12 (src/lib/snarkyjs/src/bindings/ocaml/lib/snarky_bindings.ml:17:15)
at Function.Class.<computed> [as exists] (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:3413:52)
at Object.witness (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:6439:35)
at Function.witness (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:16063:21)
at MinaNFTNameServiceContract.wrappedMethod (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:14541:78)
at Escrow.transfer (src/plugins/escrow.ts:81:13)
at Escrow.wrappedMethod (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:14446:30)
at src/escrow.ts:203:15
at .yarn/cache/o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:16769:13
at ../../../../../../workspace_root/src/lib/snarkyjs/src/bindings/ocaml/lib/snarky_bindings.ml:38:11
at ../../../../../../workspace_root/src/lib/snarky/src/base/snark0.ml:1315:40
at mark_active (src/lib/snarky/src/base/snark0.ml:1167:19)
at _piO_ (src/lib/snarky/src/base/snark0.ml:1314:17)
at as_stateful (src/lib/snarky/src/base/snark0.ml:755:15)
at run_and_check_exn (src/lib/snarky/src/base/runners.ml:115:16)
at ../../../../../../workspace_root/src/lib/snarky/src/base/snark0.ml:1313:13
at finalize_is_running (src/lib/snarky/src/base/snark0.ml:1272:15)
at run_and_check_exn (src/lib/snarky/src/base/snark0.ml:1311:7)
at Object.runUnchecked (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:4163:16)
at createTransaction (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:16768:20)
at Object.transaction (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:17208:16)
at Object.transaction (o1js-npm-0.14.1-6dd1d545d0-5ce9973c48.zip/node_modules/o1js/dist/node/index.cjs:17321:27)
at MinaNFTEscrow.transfer (src/escrow.ts:200:36)
at Object.<anonymous> (tests/escrow.test.ts:278:18)
In reality, the balance is not 0; it is 1000000000, as shown by several checks made before calling transfer() The bug exists while using testworld2; on the local blockchain, the function get() returns the correct result.
There is also a discussion on the hierarchy of Token accounts (i.e., many nested token accounts) on the discord that can be affected by this behavior: https://discord.com/channels/484437221055922177/1171202435663007804
Today, I checked my old code that throws this error, and the error is still there. I went to debug it and found out the error is being thrown when I use getAndRequireEquals() on token accounts:
@method checkFail(address: PublicKey, tokenId: Field) {
const version = this.version.getAndRequireEquals();
version.assertEquals(Field(1));
const token = new TokenAccount(address, tokenId);
// If you comment next two lines, the test will pass
const value = token.value.getAndRequireEquals();
value.assertEquals(Field(1));
}
When I use get(), tests pass:
@method checkPass(address: PublicKey, tokenId: Field) {
const version = this.version.getAndRequireEquals();
version.assertEquals(Field(1));
const token = new TokenAccount(address, tokenId);
const value = token.value.get();
value.assertEquals(Field(1));
}
The test code I use: https://github.com/dfstio/minanft-lib/blob/token-accounts/experimental/issue_token_accounts.test.ts
The discord discussion: https://discord.com/channels/484437221055922177/1261748801371373729/1262142233973362770
When @method accesses one token Account(address, tokenId), everything works as expected. When trying to access two token accounts, the following error appears while proving: