diff --git a/.github/workflows/sdk-wheels.yml b/.github/workflows/sdk-wheels.yml index d763a05..834b3d7 100644 --- a/.github/workflows/sdk-wheels.yml +++ b/.github/workflows/sdk-wheels.yml @@ -118,10 +118,13 @@ jobs: python .github/scripts/merge_testnet_so.py sdk/dist sdk/dist-testnet # Every runner here matches its wheel's platform, so install and smoke # test the actual artifact — importing BOTH networks — before it ships. + # Install by path: --find-links also consults PyPI, and once this + # version is published there pip may prefer the PyPI wheel over the + # one just built (tag-order tie on macOS/Windows). - name: Smoke test wheel shell: bash run: | - pip install --find-links sdk/dist aleo-sdk + pip install sdk/dist/aleo_sdk-*.whl python -c " from aleo.mainnet import PrivateKey as MainnetPrivateKey from aleo.testnet import PrivateKey as TestnetPrivateKey @@ -187,7 +190,7 @@ jobs: - name: Smoke test wheel shell: bash run: | - pip install --find-links sdk-abi/dist aleo-contract-abi-generator + pip install sdk-abi/dist/*.whl python -c "import aleo_abi; print(aleo_abi.generate_abi.__name__)" - name: Upload wheel uses: actions/upload-artifact@v4 @@ -251,8 +254,8 @@ jobs: python -m build shield-swap-sdk --outdir shield-swap-sdk/dist - name: Test against the built aleo-sdk wheel run: | - pip install --find-links sdk-dist aleo-sdk - pip install --find-links shield-swap-sdk/dist "shield-swap-sdk[async,mcp]" pytest pytest-asyncio + pip install sdk-dist/aleo_sdk-*.whl + pip install "$(ls shield-swap-sdk/dist/*.whl)[async,mcp]" pytest pytest-asyncio cd shield-swap-sdk && python -m pytest - name: AGENTS.md up to date run: python shield-swap-sdk/codegen/gen_context.py --check diff --git a/.github/workflows/sdk.yml b/.github/workflows/sdk.yml index 6cee53f..f8faa4f 100644 --- a/.github/workflows/sdk.yml +++ b/.github/workflows/sdk.yml @@ -72,9 +72,12 @@ jobs: maturin build --release --no-default-features --features testnet --out dist-testnet mv pyproject.toml.bak pyproject.toml python ../.github/scripts/merge_testnet_so.py dist dist-testnet + # Install the built wheel by path: --find-links also consults PyPI, and + # once the branch's version is published there pip may prefer the PyPI + # wheel over the one just built (tag-order tie on macOS/Windows). - name: Install wheel + test deps run: | - pip install --find-links dist aleo-sdk + pip install dist/aleo_sdk-*.whl pip install pytest pytest-xdist httpx pynacl responses pytest-asyncio # Fast, offline tests; -n auto parallelizes across cores. - name: pytest (fast suite) @@ -116,7 +119,7 @@ jobs: python ../.github/scripts/merge_testnet_so.py dist dist-testnet - name: Install wheel + test deps run: | - pip install --find-links dist aleo-sdk + pip install dist/aleo_sdk-*.whl pip install pytest httpx pynacl responses pytest-asyncio # The two slow tests share one module-scoped proven execution; xdist # would prove twice, so they run in a single worker on purpose. @@ -169,7 +172,7 @@ jobs: maturin build --release --manifest-path sdk-abi/Cargo.toml --out dist - name: Install wheels run: | - pip install --find-links dist aleo-sdk aleo-contract-abi-generator + pip install dist/*.whl # Run each suite from inside its package dir so pytest uses that # package's own pytest.ini (sdk-abi/pytest.ini, sdk/pytest.ini) rather # than walking up to the stale legacy root setup.cfg. diff --git a/sdk/python/aleo/_aleolib_mainnet.pyi b/sdk/python/aleo/_aleolib_mainnet.pyi index bbbfca0..cbfb6b2 100644 --- a/sdk/python/aleo/_aleolib_mainnet.pyi +++ b/sdk/python/aleo/_aleolib_mainnet.pyi @@ -957,6 +957,8 @@ class Program: def get_record_members(self, record_name: str) -> dict[str, Any]: ... def get_struct_members(self, struct_name: str) -> list[dict[str, Any]]: ... def address(self) -> Address: ... + def is_arc20(self) -> bool: ... + def is_arc22(self) -> bool: ... class ProgramID: diff --git a/sdk/python/aleo/_aleolib_testnet.pyi b/sdk/python/aleo/_aleolib_testnet.pyi index bbbfca0..cbfb6b2 100644 --- a/sdk/python/aleo/_aleolib_testnet.pyi +++ b/sdk/python/aleo/_aleolib_testnet.pyi @@ -957,6 +957,8 @@ class Program: def get_record_members(self, record_name: str) -> dict[str, Any]: ... def get_struct_members(self, struct_name: str) -> list[dict[str, Any]]: ... def address(self) -> Address: ... + def is_arc20(self) -> bool: ... + def is_arc22(self) -> bool: ... class ProgramID: diff --git a/sdk/python/tests/fixtures/arc20_token.aleo b/sdk/python/tests/fixtures/arc20_token.aleo new file mode 100644 index 0000000..37d826d --- /dev/null +++ b/sdk/python/tests/fixtures/arc20_token.aleo @@ -0,0 +1,228 @@ +program arc20_token.aleo; + +record Token: + owner as address.private; + amount as u128.private; + +struct approval: + approver as address; + spender as address; + +mapping account: + key as address.public; + value as u128.public; + +mapping approvals: + key as field.public; + value as u128.public; + +mapping settings: + key as u8.public; + value as u128.public; + +mapping token_info: + key as u8.public; + value as u8.public; + +function transfer_public: + input r0 as address.public; + input r1 as u128.public; + async transfer_public self.caller r0 r1 into r2; + output r2 as arc20_token.aleo/transfer_public.future; + +finalize transfer_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get account[r0] into r3; + sub r3 r2 into r4; + set r4 into account[r0]; + get.or_use account[r1] 0u128 into r5; + add r5 r2 into r6; + set r6 into account[r1]; + +function transfer_private: + input r0 as Token.record; + input r1 as address.private; + input r2 as u128.private; + sub r0.amount r2 into r3; + cast r0.owner r3 into r4 as Token.record; + cast r1 r2 into r5 as Token.record; + output r4 as Token.record; + output r5 as Token.record; + +function transfer_private_to_public: + input r0 as Token.record; + input r1 as address.public; + input r2 as u128.public; + sub r0.amount r2 into r3; + cast r0.owner r3 into r4 as Token.record; + async transfer_private_to_public r1 r2 into r5; + output r4 as Token.record; + output r5 as arc20_token.aleo/transfer_private_to_public.future; + +finalize transfer_private_to_public: + input r0 as address.public; + input r1 as u128.public; + get.or_use account[r0] 0u128 into r2; + add r2 r1 into r3; + set r3 into account[r0]; + +function transfer_public_to_private: + input r0 as address.private; + input r1 as u128.public; + cast r0 r1 into r2 as Token.record; + async transfer_public_to_private self.caller r1 into r3; + output r2 as Token.record; + output r3 as arc20_token.aleo/transfer_public_to_private.future; + +finalize transfer_public_to_private: + input r0 as address.public; + input r1 as u128.public; + get account[r0] into r2; + sub r2 r1 into r3; + set r3 into account[r0]; + +function transfer_public_as_signer: + input r0 as address.public; + input r1 as u128.public; + async transfer_public_as_signer self.signer r0 r1 into r2; + output r2 as arc20_token.aleo/transfer_public_as_signer.future; + +finalize transfer_public_as_signer: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get account[r0] into r3; + sub r3 r2 into r4; + set r4 into account[r0]; + get.or_use account[r1] 0u128 into r5; + add r5 r2 into r6; + set r6 into account[r1]; + +function transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + async transfer_from_public self.caller r0 r1 r2 into r3; + output r3 as arc20_token.aleo/transfer_from_public.future; + +finalize transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as address.public; + input r3 as u128.public; + cast r1 r0 into r4 as approval; + hash.bhp256 r4 into r5 as field; + get approvals[r5] into r6; + sub r6 r3 into r7; + set r7 into approvals[r5]; + get account[r1] into r8; + sub r8 r3 into r9; + set r9 into account[r1]; + get.or_use account[r2] 0u128 into r10; + add r10 r3 into r11; + set r11 into account[r2]; + +function transfer_from_public_to_private: + input r0 as address.public; + input r1 as address.private; + input r2 as u128.public; + cast r1 r2 into r3 as Token.record; + async transfer_from_public_to_private self.caller r0 r2 into r4; + output r3 as Token.record; + output r4 as arc20_token.aleo/transfer_from_public_to_private.future; + +finalize transfer_from_public_to_private: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r1 r0 into r3 as approval; + hash.bhp256 r3 into r4 as field; + get approvals[r4] into r5; + sub r5 r2 into r6; + set r6 into approvals[r4]; + get account[r1] into r7; + sub r7 r2 into r8; + set r8 into account[r1]; + +function approve_public: + input r0 as address.public; + input r1 as u128.public; + async approve_public self.caller r0 r1 into r2; + output r2 as arc20_token.aleo/approve_public.future; + +finalize approve_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r0 r1 into r3 as approval; + hash.bhp256 r3 into r4 as field; + get.or_use approvals[r4] 0u128 into r5; + add r5 r2 into r6; + set r6 into approvals[r4]; + +function unapprove_public: + input r0 as address.public; + input r1 as u128.public; + async unapprove_public self.caller r0 r1 into r2; + output r2 as arc20_token.aleo/unapprove_public.future; + +finalize unapprove_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r0 r1 into r3 as approval; + hash.bhp256 r3 into r4 as field; + get approvals[r4] into r5; + sub r5 r2 into r6; + set r6 into approvals[r4]; + +function join: + input r0 as Token.record; + input r1 as Token.record; + add r0.amount r1.amount into r2; + cast r0.owner r2 into r3 as Token.record; + output r3 as Token.record; + +function split: + input r0 as Token.record; + input r1 as u128.private; + sub r0.amount r1 into r2; + cast r0.owner r1 into r3 as Token.record; + cast r0.owner r2 into r4 as Token.record; + output r3 as Token.record; + output r4 as Token.record; + +view balance_of: + input r0 as address.public; + get.or_use account[r0] 0u128 into r1; + output r1 as u128.public; + +view allowance: + input r0 as address.public; + input r1 as address.public; + cast r0 r1 into r2 as approval; + hash.bhp256 r2 into r3 as field; + get.or_use approvals[r3] 0u128 into r4; + output r4 as u128.public; + +view supply: + get.or_use settings[0u8] 0u128 into r0; + output r0 as u128.public; + +view max_supply: + get.or_use settings[1u8] 0u128 into r0; + output r0 as u128.public; + +view decimals: + get.or_use token_info[0u8] 6u8 into r0; + output r0 as u8.public; + +view name: + cast 6577149field into r0 as identifier; + output r0 as identifier.public; + +view symbol: + cast 5526356field into r0 as identifier; + output r0 as identifier.public; diff --git a/sdk/python/tests/fixtures/arc22_token.aleo b/sdk/python/tests/fixtures/arc22_token.aleo new file mode 100644 index 0000000..d8e92b8 --- /dev/null +++ b/sdk/python/tests/fixtures/arc22_token.aleo @@ -0,0 +1,258 @@ +program arc22_token.aleo; + +record Token: + owner as address.private; + amount as u128.private; + token_id as field.private; + +record ComplianceRecord: + owner as address.private; + amount as u128.private; + sender as address.private; + recipient as address.private; + +struct MerkleProof: + siblings as [field; 16u32]; + leaf_index as u32; + +struct approval: + approver as address; + spender as address; + +mapping account: + key as address.public; + value as u128.public; + +mapping approvals: + key as field.public; + value as u128.public; + +mapping settings: + key as u8.public; + value as u128.public; + +mapping token_info: + key as u8.public; + value as u8.public; + +function approve_public: + input r0 as address.public; + input r1 as u128.public; + async approve_public self.caller r0 r1 into r2; + output r2 as arc22_token.aleo/approve_public.future; + +finalize approve_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r0 r1 into r3 as approval; + hash.bhp256 r3 into r4 as field; + get.or_use approvals[r4] 0u128 into r5; + add r5 r2 into r6; + set r6 into approvals[r4]; + +function unapprove_public: + input r0 as address.public; + input r1 as u128.public; + async unapprove_public self.caller r0 r1 into r2; + output r2 as arc22_token.aleo/unapprove_public.future; + +finalize unapprove_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r0 r1 into r3 as approval; + hash.bhp256 r3 into r4 as field; + get approvals[r4] into r5; + sub r5 r2 into r6; + set r6 into approvals[r4]; + +function transfer_public: + input r0 as address.public; + input r1 as u128.public; + async transfer_public self.caller r0 r1 into r2; + output r2 as arc22_token.aleo/transfer_public.future; + +finalize transfer_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get account[r0] into r3; + sub r3 r2 into r4; + set r4 into account[r0]; + get.or_use account[r1] 0u128 into r5; + add r5 r2 into r6; + set r6 into account[r1]; + +function transfer_private: + input r0 as address.private; + input r1 as u128.private; + input r2 as Token.record; + input r3 as [MerkleProof; 2u32].private; + sub r2.amount r1 into r4; + cast r2.owner r1 r2.owner r0 into r5 as ComplianceRecord.record; + cast r2.owner r4 r2.token_id into r6 as Token.record; + cast r0 r1 r2.token_id into r7 as Token.record; + async transfer_private r0 r1 into r8; + output r5 as ComplianceRecord.record; + output r6 as Token.record; + output r7 as Token.record; + output r8 as arc22_token.aleo/transfer_private.future; + +finalize transfer_private: + input r0 as address.public; + input r1 as u128.public; + get.or_use account[r0] 0u128 into r2; + add r2 r1 into r3; + set r3 into account[r0]; + +function transfer_private_to_public: + input r0 as address.public; + input r1 as u128.public; + input r2 as Token.record; + input r3 as [MerkleProof; 2u32].private; + sub r2.amount r1 into r4; + cast r2.owner r1 r2.owner r0 into r5 as ComplianceRecord.record; + cast r2.owner r4 r2.token_id into r6 as Token.record; + async transfer_private_to_public r0 r1 into r7; + output r5 as ComplianceRecord.record; + output r6 as Token.record; + output r7 as arc22_token.aleo/transfer_private_to_public.future; + +finalize transfer_private_to_public: + input r0 as address.public; + input r1 as u128.public; + get.or_use account[r0] 0u128 into r2; + add r2 r1 into r3; + set r3 into account[r0]; + +function transfer_public_to_private: + input r0 as address.private; + input r1 as u128.public; + cast r0 r1 self.caller r0 into r2 as ComplianceRecord.record; + cast r0 r1 0field into r3 as Token.record; + async transfer_public_to_private self.caller r1 into r4; + output r2 as ComplianceRecord.record; + output r3 as Token.record; + output r4 as arc22_token.aleo/transfer_public_to_private.future; + +finalize transfer_public_to_private: + input r0 as address.public; + input r1 as u128.public; + get account[r0] into r2; + sub r2 r1 into r3; + set r3 into account[r0]; + +function transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + async transfer_from_public self.caller r0 r1 r2 into r3; + output r3 as arc22_token.aleo/transfer_from_public.future; + +finalize transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as address.public; + input r3 as u128.public; + cast r1 r0 into r4 as approval; + hash.bhp256 r4 into r5 as field; + get approvals[r5] into r6; + sub r6 r3 into r7; + set r7 into approvals[r5]; + get account[r1] into r8; + sub r8 r3 into r9; + set r9 into account[r1]; + get.or_use account[r2] 0u128 into r10; + add r10 r3 into r11; + set r11 into account[r2]; + +function transfer_from_public_to_private: + input r0 as address.public; + input r1 as address.private; + input r2 as u128.public; + cast r1 r2 r0 r1 into r3 as ComplianceRecord.record; + cast r1 r2 0field into r4 as Token.record; + async transfer_from_public_to_private self.caller r0 r2 into r5; + output r3 as ComplianceRecord.record; + output r4 as Token.record; + output r5 as arc22_token.aleo/transfer_from_public_to_private.future; + +finalize transfer_from_public_to_private: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r1 r0 into r3 as approval; + hash.bhp256 r3 into r4 as field; + get approvals[r4] into r5; + sub r5 r2 into r6; + set r6 into approvals[r4]; + get account[r1] into r7; + sub r7 r2 into r8; + set r8 into account[r1]; + +function transfer_public_as_signer: + input r0 as address.public; + input r1 as u128.public; + async transfer_public_as_signer self.signer r0 r1 into r2; + output r2 as arc22_token.aleo/transfer_public_as_signer.future; + +finalize transfer_public_as_signer: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get account[r0] into r3; + sub r3 r2 into r4; + set r4 into account[r0]; + get.or_use account[r1] 0u128 into r5; + add r5 r2 into r6; + set r6 into account[r1]; + +function join: + input r0 as Token.record; + input r1 as Token.record; + add r0.amount r1.amount into r2; + cast r0.owner r2 r0.token_id into r3 as Token.record; + output r3 as Token.record; + +function split: + input r0 as Token.record; + input r1 as u128.private; + sub r0.amount r1 into r2; + cast r0.owner r1 r0.token_id into r3 as Token.record; + cast r0.owner r2 r0.token_id into r4 as Token.record; + output r3 as Token.record; + output r4 as Token.record; + +view balance_of: + input r0 as address.public; + get.or_use account[r0] 0u128 into r1; + output r1 as u128.public; + +view allowance: + input r0 as address.public; + input r1 as address.public; + cast r0 r1 into r2 as approval; + hash.bhp256 r2 into r3 as field; + get.or_use approvals[r3] 0u128 into r4; + output r4 as u128.public; + +view supply: + get.or_use settings[0u8] 0u128 into r0; + output r0 as u128.public; + +view max_supply: + get.or_use settings[1u8] 0u128 into r0; + output r0 as u128.public; + +view decimals: + get.or_use token_info[0u8] 6u8 into r0; + output r0 as u8.public; + +view name: + cast 6577149field into r0 as identifier; + output r0 as identifier.public; + +view symbol: + cast 5526356field into r0 as identifier; + output r0 as identifier.public; diff --git a/sdk/python/tests/fixtures/compliant_token_template.aleo b/sdk/python/tests/fixtures/compliant_token_template.aleo new file mode 100644 index 0000000..f2f9001 --- /dev/null +++ b/sdk/python/tests/fixtures/compliant_token_template.aleo @@ -0,0 +1,1174 @@ +import merkle_tree.aleo; +import multisig_core.aleo; +import freezelist.aleo; +program compliant_token_template.aleo; + +record Token: + owner as address.private; + amount as u128.private; + +record ComplianceRecord: + owner as address.private; + amount as u128.private; + sender as address.private; + recipient as address.private; + +struct ChecksumEdition: + checksum as [u8; 32u32]; + edition as u16; + +struct TokenInfo: + name as u128; + symbol as u128; + decimals as u8; + supply as u128; + max_supply as u128; + +struct TokenAllowance: + account as address; + spender as address; + +struct Optional__ATAkdHctJwx: + is_some as boolean; + val as boolean; + +struct Optional__An66AtVsP75: + is_some as boolean; + val as TokenInfo; + +mapping balances: + key as address.public; + value as u128.public; + +mapping allowances: + key as TokenAllowance.public; + value as u128.public; + +mapping address_to_role: + key as address.public; + value as u16.public; + +mapping token_info__: + key as boolean.public; + value as TokenInfo.public; + +mapping pause__: + key as boolean.public; + value as boolean.public; + +mapping initialized__: + key as boolean.public; + value as boolean.public; + +function get_signing_op_id_for_deploy: + input r0 as [u8; 32u32].private; + input r1 as u16.private; + cast r0 r1 into r2 as ChecksumEdition; + hash.bhp256 r2 into r3 as field; + output r3 as field.private; + +function update_role: + input r0 as address.public; + input r1 as u16.private; + async update_role self.caller r0 r1 into r2; + output r2 as compliant_token_template.aleo/update_role.future; + +finalize update_role: + input r0 as address.public; + input r1 as address.public; + input r2 as u16.public; + get address_to_role[r0] into r3; + and r3 8u16 into r4; + is.eq r4 8u16 into r5; + assert.eq r5 true; + is.eq r0 r1 into r6; + branch.eq r6 false to end_then_0_0; + and r2 8u16 into r7; + is.eq r7 8u16 into r8; + assert.eq r8 true; + branch.eq true true to end_otherwise_0_1; + position end_then_0_0; + position end_otherwise_0_1; + set r2 into address_to_role[r1]; + +function initialize: + input r0 as u128.public; + input r1 as u128.public; + input r2 as u8.public; + input r3 as u128.public; + input r4 as address.public; + async initialize self.caller r4 r0 r1 r2 r3 into r5; + output r5 as compliant_token_template.aleo/initialize.future; + +finalize initialize: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + input r3 as u128.public; + input r4 as u8.public; + input r5 as u128.public; + contains initialized__[false] into r6; + get.or_use initialized__[false] false into r7; + ternary r6 r7 false into r8; + cast r6 r8 into r9 as Optional__ATAkdHctJwx; + ternary r9.is_some r9.val false into r10; + assert.eq r10 false; + assert.eq r0 aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px; + set 8u16 into address_to_role[r1]; + cast r2 r3 r4 0u128 r5 into r11 as TokenInfo; + set r11 into token_info__[false]; + set false into pause__[false]; + set true into initialized__[false]; + +function mint_public: + input r0 as address.public; + input r1 as u128.public; + async mint_public self.caller r0 r1 into r2; + output r2 as compliant_token_template.aleo/mint_public.future; + +finalize mint_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get address_to_role[r0] into r3; + and r3 1u16 into r4; + is.eq r4 1u16 into r5; + assert.eq r5 true; + contains pause__[false] into r6; + get.or_use pause__[false] false into r7; + ternary r6 r7 false into r8; + cast r6 r8 into r9 as Optional__ATAkdHctJwx; + assert.eq r9.is_some true; + assert.eq r9.val false; + get.or_use balances[r1] 0u128 into r10; + add r2 r10 into r11; + set r11 into balances[r1]; + contains token_info__[false] into r12; + cast 0u128 0u128 0u8 0u128 0u128 into r13 as TokenInfo; + get.or_use token_info__[false] r13 into r14; + cast 0u128 0u128 0u8 0u128 0u128 into r15 as TokenInfo; + ternary r12 r14.name r15.name into r16; + ternary r12 r14.symbol r15.symbol into r17; + ternary r12 r14.decimals r15.decimals into r18; + ternary r12 r14.supply r15.supply into r19; + ternary r12 r14.max_supply r15.max_supply into r20; + cast r16 r17 r18 r19 r20 into r21 as TokenInfo; + cast r12 r21 into r22 as Optional__An66AtVsP75; + assert.eq r22.is_some true; + add r22.val.supply r2 into r23; + lte r23 r22.val.max_supply into r24; + assert.eq r24 true; + cast r22.val.name r22.val.symbol r22.val.decimals r23 r22.val.max_supply into r25 as TokenInfo; + set r25 into token_info__[false]; + +function mint_private: + input r0 as address.private; + input r1 as u128.public; + cast r0 r1 into r2 as Token.record; + cast aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px r1 aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc r0 into r3 as ComplianceRecord.record; + async mint_private self.caller r1 into r4; + output r3 as ComplianceRecord.record; + output r2 as Token.record; + output r4 as compliant_token_template.aleo/mint_private.future; + +finalize mint_private: + input r0 as address.public; + input r1 as u128.public; + get address_to_role[r0] into r2; + and r2 1u16 into r3; + is.eq r3 1u16 into r4; + assert.eq r4 true; + contains pause__[false] into r5; + get.or_use pause__[false] false into r6; + ternary r5 r6 false into r7; + cast r5 r7 into r8 as Optional__ATAkdHctJwx; + assert.eq r8.is_some true; + assert.eq r8.val false; + contains token_info__[false] into r9; + cast 0u128 0u128 0u8 0u128 0u128 into r10 as TokenInfo; + get.or_use token_info__[false] r10 into r11; + cast 0u128 0u128 0u8 0u128 0u128 into r12 as TokenInfo; + ternary r9 r11.name r12.name into r13; + ternary r9 r11.symbol r12.symbol into r14; + ternary r9 r11.decimals r12.decimals into r15; + ternary r9 r11.supply r12.supply into r16; + ternary r9 r11.max_supply r12.max_supply into r17; + cast r13 r14 r15 r16 r17 into r18 as TokenInfo; + cast r9 r18 into r19 as Optional__An66AtVsP75; + assert.eq r19.is_some true; + add r19.val.supply r1 into r20; + lte r20 r19.val.max_supply into r21; + assert.eq r21 true; + cast r19.val.name r19.val.symbol r19.val.decimals r20 r19.val.max_supply into r22 as TokenInfo; + set r22 into token_info__[false]; + +function burn_public: + input r0 as address.public; + input r1 as u128.public; + async burn_public self.caller r0 r1 into r2; + output r2 as compliant_token_template.aleo/burn_public.future; + +finalize burn_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get address_to_role[r0] into r3; + and r3 2u16 into r4; + is.eq r4 2u16 into r5; + assert.eq r5 true; + contains pause__[false] into r6; + get.or_use pause__[false] false into r7; + ternary r6 r7 false into r8; + cast r6 r8 into r9 as Optional__ATAkdHctJwx; + assert.eq r9.is_some true; + assert.eq r9.val false; + get balances[r1] into r10; + sub r10 r2 into r11; + set r11 into balances[r1]; + contains token_info__[false] into r12; + cast 0u128 0u128 0u8 0u128 0u128 into r13 as TokenInfo; + get.or_use token_info__[false] r13 into r14; + cast 0u128 0u128 0u8 0u128 0u128 into r15 as TokenInfo; + ternary r12 r14.name r15.name into r16; + ternary r12 r14.symbol r15.symbol into r17; + ternary r12 r14.decimals r15.decimals into r18; + ternary r12 r14.supply r15.supply into r19; + ternary r12 r14.max_supply r15.max_supply into r20; + cast r16 r17 r18 r19 r20 into r21 as TokenInfo; + cast r12 r21 into r22 as Optional__An66AtVsP75; + assert.eq r22.is_some true; + sub r22.val.supply r2 into r23; + cast r22.val.name r22.val.symbol r22.val.decimals r23 r22.val.max_supply into r24 as TokenInfo; + set r24 into token_info__[false]; + +function burn_private: + input r0 as Token.record; + input r1 as u128.public; + sub r0.amount r1 into r2; + cast r0.owner r2 into r3 as Token.record; + cast aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px r1 r0.owner aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc into r4 as ComplianceRecord.record; + async burn_private self.caller r1 into r5; + output r4 as ComplianceRecord.record; + output r3 as Token.record; + output r5 as compliant_token_template.aleo/burn_private.future; + +finalize burn_private: + input r0 as address.public; + input r1 as u128.public; + get address_to_role[r0] into r2; + and r2 2u16 into r3; + is.eq r3 2u16 into r4; + assert.eq r4 true; + contains pause__[false] into r5; + get.or_use pause__[false] false into r6; + ternary r5 r6 false into r7; + cast r5 r7 into r8 as Optional__ATAkdHctJwx; + assert.eq r8.is_some true; + assert.eq r8.val false; + contains token_info__[false] into r9; + cast 0u128 0u128 0u8 0u128 0u128 into r10 as TokenInfo; + get.or_use token_info__[false] r10 into r11; + cast 0u128 0u128 0u8 0u128 0u128 into r12 as TokenInfo; + ternary r9 r11.name r12.name into r13; + ternary r9 r11.symbol r12.symbol into r14; + ternary r9 r11.decimals r12.decimals into r15; + ternary r9 r11.supply r12.supply into r16; + ternary r9 r11.max_supply r12.max_supply into r17; + cast r13 r14 r15 r16 r17 into r18 as TokenInfo; + cast r9 r18 into r19 as Optional__An66AtVsP75; + assert.eq r19.is_some true; + sub r19.val.supply r1 into r20; + cast r19.val.name r19.val.symbol r19.val.decimals r20 r19.val.max_supply into r21 as TokenInfo; + set r21 into token_info__[false]; + +function transfer_public: + input r0 as address.public; + input r1 as u128.public; + async transfer_public self.caller r0 r1 into r2; + output r2 as compliant_token_template.aleo/transfer_public.future; + +finalize transfer_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get.or_use freezelist.aleo/freeze_list[r0] false into r3; + assert.eq r3 false; + get.or_use freezelist.aleo/freeze_list[r1] false into r4; + assert.eq r4 false; + contains pause__[false] into r5; + get.or_use pause__[false] false into r6; + ternary r5 r6 false into r7; + cast r5 r7 into r8 as Optional__ATAkdHctJwx; + assert.eq r8.is_some true; + assert.eq r8.val false; + get balances[r0] into r9; + sub r9 r2 into r10; + set r10 into balances[r0]; + get.or_use balances[r1] 0u128 into r11; + add r11 r2 into r12; + set r12 into balances[r1]; + +function transfer_public_as_signer: + input r0 as address.public; + input r1 as u128.public; + async transfer_public_as_signer self.signer r0 r1 into r2; + output r2 as compliant_token_template.aleo/transfer_public_as_signer.future; + +finalize transfer_public_as_signer: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get.or_use freezelist.aleo/freeze_list[r0] false into r3; + assert.eq r3 false; + get.or_use freezelist.aleo/freeze_list[r1] false into r4; + assert.eq r4 false; + contains pause__[false] into r5; + get.or_use pause__[false] false into r6; + ternary r5 r6 false into r7; + cast r5 r7 into r8 as Optional__ATAkdHctJwx; + assert.eq r8.is_some true; + assert.eq r8.val false; + get balances[r0] into r9; + sub r9 r2 into r10; + set r10 into balances[r0]; + get.or_use balances[r1] 0u128 into r11; + add r11 r2 into r12; + set r12 into balances[r1]; + +function approve_public: + input r0 as address.public; + input r1 as u128.public; + cast self.caller r0 into r2 as TokenAllowance; + async approve_public r2 r1 into r3; + output r3 as compliant_token_template.aleo/approve_public.future; + +finalize approve_public: + input r0 as TokenAllowance.public; + input r1 as u128.public; + contains pause__[false] into r2; + get.or_use pause__[false] false into r3; + ternary r2 r3 false into r4; + cast r2 r4 into r5 as Optional__ATAkdHctJwx; + assert.eq r5.is_some true; + assert.eq r5.val false; + get.or_use allowances[r0] 0u128 into r6; + add r6 r1 into r7; + set r7 into allowances[r0]; + +function unapprove_public: + input r0 as address.public; + input r1 as u128.public; + cast self.caller r0 into r2 as TokenAllowance; + async unapprove_public r2 r1 into r3; + output r3 as compliant_token_template.aleo/unapprove_public.future; + +finalize unapprove_public: + input r0 as TokenAllowance.public; + input r1 as u128.public; + contains pause__[false] into r2; + get.or_use pause__[false] false into r3; + ternary r2 r3 false into r4; + cast r2 r4 into r5 as Optional__ATAkdHctJwx; + assert.eq r5.is_some true; + assert.eq r5.val false; + get allowances[r0] into r6; + sub r6 r1 into r7; + set r7 into allowances[r0]; + +function transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r0 self.caller into r3 as TokenAllowance; + async transfer_from_public r0 r1 r3 r2 into r4; + output r4 as compliant_token_template.aleo/transfer_from_public.future; + +finalize transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as TokenAllowance.public; + input r3 as u128.public; + get.or_use freezelist.aleo/freeze_list[r0] false into r4; + assert.eq r4 false; + get.or_use freezelist.aleo/freeze_list[r1] false into r5; + assert.eq r5 false; + contains pause__[false] into r6; + get.or_use pause__[false] false into r7; + ternary r6 r7 false into r8; + cast r6 r8 into r9 as Optional__ATAkdHctJwx; + assert.eq r9.is_some true; + assert.eq r9.val false; + get allowances[r2] into r10; + sub r10 r3 into r11; + set r11 into allowances[r2]; + get balances[r0] into r12; + sub r12 r3 into r13; + set r13 into balances[r0]; + get.or_use balances[r1] 0u128 into r14; + add r14 r3 into r15; + set r15 into balances[r1]; + +function transfer_public_to_private: + input r0 as address.private; + input r1 as u128.public; + cast r0 r1 into r2 as Token.record; + cast aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px r1 self.caller r0 into r3 as ComplianceRecord.record; + async transfer_public_to_private self.caller r1 into r4; + output r3 as ComplianceRecord.record; + output r2 as Token.record; + output r4 as compliant_token_template.aleo/transfer_public_to_private.future; + +finalize transfer_public_to_private: + input r0 as address.public; + input r1 as u128.public; + get.or_use freezelist.aleo/freeze_list[r0] false into r2; + assert.eq r2 false; + contains pause__[false] into r3; + get.or_use pause__[false] false into r4; + ternary r3 r4 false into r5; + cast r3 r5 into r6 as Optional__ATAkdHctJwx; + assert.eq r6.is_some true; + assert.eq r6.val false; + get balances[r0] into r7; + sub r7 r1 into r8; + set r8 into balances[r0]; + +function transfer_from_public_to_private: + input r0 as address.public; + input r1 as address.private; + input r2 as u128.public; + cast r1 r2 into r3 as Token.record; + cast r0 self.caller into r4 as TokenAllowance; + cast aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px r2 r0 r1 into r5 as ComplianceRecord.record; + async transfer_from_public_to_private r0 r4 r2 into r6; + output r5 as ComplianceRecord.record; + output r3 as Token.record; + output r6 as compliant_token_template.aleo/transfer_from_public_to_private.future; + +finalize transfer_from_public_to_private: + input r0 as address.public; + input r1 as TokenAllowance.public; + input r2 as u128.public; + get.or_use freezelist.aleo/freeze_list[r0] false into r3; + assert.eq r3 false; + contains pause__[false] into r4; + get.or_use pause__[false] false into r5; + ternary r4 r5 false into r6; + cast r4 r6 into r7 as Optional__ATAkdHctJwx; + assert.eq r7.is_some true; + assert.eq r7.val false; + get allowances[r1] into r8; + sub r8 r2 into r9; + set r9 into allowances[r1]; + get balances[r0] into r10; + sub r10 r2 into r11; + set r11 into balances[r0]; + +closure verify_non_inclusion: + input r0 as address; + input r1 as [freezelist.aleo/MerkleProof; 2u32]; + rem r1[0u32].leaf_index 2u32 into r2; + is.eq r2 0u32 into r3; + cast 1field r1[0u32].siblings[0u32] r1[0u32].siblings[1u32] into r4 as [field; 3u32]; + cast 1field r1[0u32].siblings[1u32] r1[0u32].siblings[0u32] into r5 as [field; 3u32]; + ternary r3 r4[0u32] r5[0u32] into r6; + ternary r3 r4[1u32] r5[1u32] into r7; + ternary r3 r4[2u32] r5[2u32] into r8; + cast r6 r7 r8 into r9 as [field; 3u32]; + hash.psd4 r9 into r10 as field; + is.eq r1[0u32].siblings[2u32] 0field into r11; + ternary r11 1u32 15u32 into r12; + div r1[0u32].leaf_index 2u32 into r13; + rem r13 2u32 into r14; + is.eq r14 0u32 into r15; + cast 0field r10 r1[0u32].siblings[2u32] into r16 as [field; 3u32]; + cast 0field r1[0u32].siblings[2u32] r10 into r17 as [field; 3u32]; + ternary r15 r16[0u32] r17[0u32] into r18; + ternary r15 r16[1u32] r17[1u32] into r19; + ternary r15 r16[2u32] r17[2u32] into r20; + cast r18 r19 r20 into r21 as [field; 3u32]; + is.eq r1[0u32].siblings[2u32] 0field into r22; + hash.psd4 r21 into r23 as field; + ternary r22 r10 r23 into r24; + is.eq r1[0u32].siblings[3u32] 0field into r25; + is.eq r12 15u32 into r26; + and r25 r26 into r27; + ternary r27 2u32 r12 into r28; + div r1[0u32].leaf_index 4u32 into r29; + rem r29 2u32 into r30; + is.eq r30 0u32 into r31; + cast 0field r24 r1[0u32].siblings[3u32] into r32 as [field; 3u32]; + cast 0field r1[0u32].siblings[3u32] r24 into r33 as [field; 3u32]; + ternary r31 r32[0u32] r33[0u32] into r34; + ternary r31 r32[1u32] r33[1u32] into r35; + ternary r31 r32[2u32] r33[2u32] into r36; + cast r34 r35 r36 into r37 as [field; 3u32]; + is.eq r1[0u32].siblings[3u32] 0field into r38; + hash.psd4 r37 into r39 as field; + ternary r38 r24 r39 into r40; + is.eq r1[0u32].siblings[4u32] 0field into r41; + is.eq r28 15u32 into r42; + and r41 r42 into r43; + ternary r43 3u32 r28 into r44; + div r1[0u32].leaf_index 8u32 into r45; + rem r45 2u32 into r46; + is.eq r46 0u32 into r47; + cast 0field r40 r1[0u32].siblings[4u32] into r48 as [field; 3u32]; + cast 0field r1[0u32].siblings[4u32] r40 into r49 as [field; 3u32]; + ternary r47 r48[0u32] r49[0u32] into r50; + ternary r47 r48[1u32] r49[1u32] into r51; + ternary r47 r48[2u32] r49[2u32] into r52; + cast r50 r51 r52 into r53 as [field; 3u32]; + is.eq r1[0u32].siblings[4u32] 0field into r54; + hash.psd4 r53 into r55 as field; + ternary r54 r40 r55 into r56; + is.eq r1[0u32].siblings[5u32] 0field into r57; + is.eq r44 15u32 into r58; + and r57 r58 into r59; + ternary r59 4u32 r44 into r60; + div r1[0u32].leaf_index 16u32 into r61; + rem r61 2u32 into r62; + is.eq r62 0u32 into r63; + cast 0field r56 r1[0u32].siblings[5u32] into r64 as [field; 3u32]; + cast 0field r1[0u32].siblings[5u32] r56 into r65 as [field; 3u32]; + ternary r63 r64[0u32] r65[0u32] into r66; + ternary r63 r64[1u32] r65[1u32] into r67; + ternary r63 r64[2u32] r65[2u32] into r68; + cast r66 r67 r68 into r69 as [field; 3u32]; + is.eq r1[0u32].siblings[5u32] 0field into r70; + hash.psd4 r69 into r71 as field; + ternary r70 r56 r71 into r72; + is.eq r1[0u32].siblings[6u32] 0field into r73; + is.eq r60 15u32 into r74; + and r73 r74 into r75; + ternary r75 5u32 r60 into r76; + div r1[0u32].leaf_index 32u32 into r77; + rem r77 2u32 into r78; + is.eq r78 0u32 into r79; + cast 0field r72 r1[0u32].siblings[6u32] into r80 as [field; 3u32]; + cast 0field r1[0u32].siblings[6u32] r72 into r81 as [field; 3u32]; + ternary r79 r80[0u32] r81[0u32] into r82; + ternary r79 r80[1u32] r81[1u32] into r83; + ternary r79 r80[2u32] r81[2u32] into r84; + cast r82 r83 r84 into r85 as [field; 3u32]; + is.eq r1[0u32].siblings[6u32] 0field into r86; + hash.psd4 r85 into r87 as field; + ternary r86 r72 r87 into r88; + is.eq r1[0u32].siblings[7u32] 0field into r89; + is.eq r76 15u32 into r90; + and r89 r90 into r91; + ternary r91 6u32 r76 into r92; + div r1[0u32].leaf_index 64u32 into r93; + rem r93 2u32 into r94; + is.eq r94 0u32 into r95; + cast 0field r88 r1[0u32].siblings[7u32] into r96 as [field; 3u32]; + cast 0field r1[0u32].siblings[7u32] r88 into r97 as [field; 3u32]; + ternary r95 r96[0u32] r97[0u32] into r98; + ternary r95 r96[1u32] r97[1u32] into r99; + ternary r95 r96[2u32] r97[2u32] into r100; + cast r98 r99 r100 into r101 as [field; 3u32]; + is.eq r1[0u32].siblings[7u32] 0field into r102; + hash.psd4 r101 into r103 as field; + ternary r102 r88 r103 into r104; + is.eq r1[0u32].siblings[8u32] 0field into r105; + is.eq r92 15u32 into r106; + and r105 r106 into r107; + ternary r107 7u32 r92 into r108; + div r1[0u32].leaf_index 128u32 into r109; + rem r109 2u32 into r110; + is.eq r110 0u32 into r111; + cast 0field r104 r1[0u32].siblings[8u32] into r112 as [field; 3u32]; + cast 0field r1[0u32].siblings[8u32] r104 into r113 as [field; 3u32]; + ternary r111 r112[0u32] r113[0u32] into r114; + ternary r111 r112[1u32] r113[1u32] into r115; + ternary r111 r112[2u32] r113[2u32] into r116; + cast r114 r115 r116 into r117 as [field; 3u32]; + is.eq r1[0u32].siblings[8u32] 0field into r118; + hash.psd4 r117 into r119 as field; + ternary r118 r104 r119 into r120; + is.eq r1[0u32].siblings[9u32] 0field into r121; + is.eq r108 15u32 into r122; + and r121 r122 into r123; + ternary r123 8u32 r108 into r124; + div r1[0u32].leaf_index 256u32 into r125; + rem r125 2u32 into r126; + is.eq r126 0u32 into r127; + cast 0field r120 r1[0u32].siblings[9u32] into r128 as [field; 3u32]; + cast 0field r1[0u32].siblings[9u32] r120 into r129 as [field; 3u32]; + ternary r127 r128[0u32] r129[0u32] into r130; + ternary r127 r128[1u32] r129[1u32] into r131; + ternary r127 r128[2u32] r129[2u32] into r132; + cast r130 r131 r132 into r133 as [field; 3u32]; + is.eq r1[0u32].siblings[9u32] 0field into r134; + hash.psd4 r133 into r135 as field; + ternary r134 r120 r135 into r136; + is.eq r1[0u32].siblings[10u32] 0field into r137; + is.eq r124 15u32 into r138; + and r137 r138 into r139; + ternary r139 9u32 r124 into r140; + div r1[0u32].leaf_index 512u32 into r141; + rem r141 2u32 into r142; + is.eq r142 0u32 into r143; + cast 0field r136 r1[0u32].siblings[10u32] into r144 as [field; 3u32]; + cast 0field r1[0u32].siblings[10u32] r136 into r145 as [field; 3u32]; + ternary r143 r144[0u32] r145[0u32] into r146; + ternary r143 r144[1u32] r145[1u32] into r147; + ternary r143 r144[2u32] r145[2u32] into r148; + cast r146 r147 r148 into r149 as [field; 3u32]; + is.eq r1[0u32].siblings[10u32] 0field into r150; + hash.psd4 r149 into r151 as field; + ternary r150 r136 r151 into r152; + is.eq r1[0u32].siblings[11u32] 0field into r153; + is.eq r140 15u32 into r154; + and r153 r154 into r155; + ternary r155 10u32 r140 into r156; + div r1[0u32].leaf_index 1024u32 into r157; + rem r157 2u32 into r158; + is.eq r158 0u32 into r159; + cast 0field r152 r1[0u32].siblings[11u32] into r160 as [field; 3u32]; + cast 0field r1[0u32].siblings[11u32] r152 into r161 as [field; 3u32]; + ternary r159 r160[0u32] r161[0u32] into r162; + ternary r159 r160[1u32] r161[1u32] into r163; + ternary r159 r160[2u32] r161[2u32] into r164; + cast r162 r163 r164 into r165 as [field; 3u32]; + is.eq r1[0u32].siblings[11u32] 0field into r166; + hash.psd4 r165 into r167 as field; + ternary r166 r152 r167 into r168; + is.eq r1[0u32].siblings[12u32] 0field into r169; + is.eq r156 15u32 into r170; + and r169 r170 into r171; + ternary r171 11u32 r156 into r172; + div r1[0u32].leaf_index 2048u32 into r173; + rem r173 2u32 into r174; + is.eq r174 0u32 into r175; + cast 0field r168 r1[0u32].siblings[12u32] into r176 as [field; 3u32]; + cast 0field r1[0u32].siblings[12u32] r168 into r177 as [field; 3u32]; + ternary r175 r176[0u32] r177[0u32] into r178; + ternary r175 r176[1u32] r177[1u32] into r179; + ternary r175 r176[2u32] r177[2u32] into r180; + cast r178 r179 r180 into r181 as [field; 3u32]; + is.eq r1[0u32].siblings[12u32] 0field into r182; + hash.psd4 r181 into r183 as field; + ternary r182 r168 r183 into r184; + is.eq r1[0u32].siblings[13u32] 0field into r185; + is.eq r172 15u32 into r186; + and r185 r186 into r187; + ternary r187 12u32 r172 into r188; + div r1[0u32].leaf_index 4096u32 into r189; + rem r189 2u32 into r190; + is.eq r190 0u32 into r191; + cast 0field r184 r1[0u32].siblings[13u32] into r192 as [field; 3u32]; + cast 0field r1[0u32].siblings[13u32] r184 into r193 as [field; 3u32]; + ternary r191 r192[0u32] r193[0u32] into r194; + ternary r191 r192[1u32] r193[1u32] into r195; + ternary r191 r192[2u32] r193[2u32] into r196; + cast r194 r195 r196 into r197 as [field; 3u32]; + is.eq r1[0u32].siblings[13u32] 0field into r198; + hash.psd4 r197 into r199 as field; + ternary r198 r184 r199 into r200; + is.eq r1[0u32].siblings[14u32] 0field into r201; + is.eq r188 15u32 into r202; + and r201 r202 into r203; + ternary r203 13u32 r188 into r204; + div r1[0u32].leaf_index 8192u32 into r205; + rem r205 2u32 into r206; + is.eq r206 0u32 into r207; + cast 0field r200 r1[0u32].siblings[14u32] into r208 as [field; 3u32]; + cast 0field r1[0u32].siblings[14u32] r200 into r209 as [field; 3u32]; + ternary r207 r208[0u32] r209[0u32] into r210; + ternary r207 r208[1u32] r209[1u32] into r211; + ternary r207 r208[2u32] r209[2u32] into r212; + cast r210 r211 r212 into r213 as [field; 3u32]; + is.eq r1[0u32].siblings[14u32] 0field into r214; + hash.psd4 r213 into r215 as field; + ternary r214 r200 r215 into r216; + is.eq r1[0u32].siblings[15u32] 0field into r217; + is.eq r204 15u32 into r218; + and r217 r218 into r219; + ternary r219 14u32 r204 into r220; + div r1[0u32].leaf_index 16384u32 into r221; + rem r221 2u32 into r222; + is.eq r222 0u32 into r223; + cast 0field r216 r1[0u32].siblings[15u32] into r224 as [field; 3u32]; + cast 0field r1[0u32].siblings[15u32] r216 into r225 as [field; 3u32]; + ternary r223 r224[0u32] r225[0u32] into r226; + ternary r223 r224[1u32] r225[1u32] into r227; + ternary r223 r224[2u32] r225[2u32] into r228; + cast r226 r227 r228 into r229 as [field; 3u32]; + is.eq r1[0u32].siblings[15u32] 0field into r230; + hash.psd4 r229 into r231 as field; + ternary r230 r216 r231 into r232; + rem r1[1u32].leaf_index 2u32 into r233; + is.eq r233 0u32 into r234; + cast 1field r1[1u32].siblings[0u32] r1[1u32].siblings[1u32] into r235 as [field; 3u32]; + cast 1field r1[1u32].siblings[1u32] r1[1u32].siblings[0u32] into r236 as [field; 3u32]; + ternary r234 r235[0u32] r236[0u32] into r237; + ternary r234 r235[1u32] r236[1u32] into r238; + ternary r234 r235[2u32] r236[2u32] into r239; + cast r237 r238 r239 into r240 as [field; 3u32]; + hash.psd4 r240 into r241 as field; + is.eq r1[1u32].siblings[2u32] 0field into r242; + ternary r242 1u32 15u32 into r243; + div r1[1u32].leaf_index 2u32 into r244; + rem r244 2u32 into r245; + is.eq r245 0u32 into r246; + cast 0field r241 r1[1u32].siblings[2u32] into r247 as [field; 3u32]; + cast 0field r1[1u32].siblings[2u32] r241 into r248 as [field; 3u32]; + ternary r246 r247[0u32] r248[0u32] into r249; + ternary r246 r247[1u32] r248[1u32] into r250; + ternary r246 r247[2u32] r248[2u32] into r251; + cast r249 r250 r251 into r252 as [field; 3u32]; + is.eq r1[1u32].siblings[2u32] 0field into r253; + hash.psd4 r252 into r254 as field; + ternary r253 r241 r254 into r255; + is.eq r1[1u32].siblings[3u32] 0field into r256; + is.eq r243 15u32 into r257; + and r256 r257 into r258; + ternary r258 2u32 r243 into r259; + div r1[1u32].leaf_index 4u32 into r260; + rem r260 2u32 into r261; + is.eq r261 0u32 into r262; + cast 0field r255 r1[1u32].siblings[3u32] into r263 as [field; 3u32]; + cast 0field r1[1u32].siblings[3u32] r255 into r264 as [field; 3u32]; + ternary r262 r263[0u32] r264[0u32] into r265; + ternary r262 r263[1u32] r264[1u32] into r266; + ternary r262 r263[2u32] r264[2u32] into r267; + cast r265 r266 r267 into r268 as [field; 3u32]; + is.eq r1[1u32].siblings[3u32] 0field into r269; + hash.psd4 r268 into r270 as field; + ternary r269 r255 r270 into r271; + is.eq r1[1u32].siblings[4u32] 0field into r272; + is.eq r259 15u32 into r273; + and r272 r273 into r274; + ternary r274 3u32 r259 into r275; + div r1[1u32].leaf_index 8u32 into r276; + rem r276 2u32 into r277; + is.eq r277 0u32 into r278; + cast 0field r271 r1[1u32].siblings[4u32] into r279 as [field; 3u32]; + cast 0field r1[1u32].siblings[4u32] r271 into r280 as [field; 3u32]; + ternary r278 r279[0u32] r280[0u32] into r281; + ternary r278 r279[1u32] r280[1u32] into r282; + ternary r278 r279[2u32] r280[2u32] into r283; + cast r281 r282 r283 into r284 as [field; 3u32]; + is.eq r1[1u32].siblings[4u32] 0field into r285; + hash.psd4 r284 into r286 as field; + ternary r285 r271 r286 into r287; + is.eq r1[1u32].siblings[5u32] 0field into r288; + is.eq r275 15u32 into r289; + and r288 r289 into r290; + ternary r290 4u32 r275 into r291; + div r1[1u32].leaf_index 16u32 into r292; + rem r292 2u32 into r293; + is.eq r293 0u32 into r294; + cast 0field r287 r1[1u32].siblings[5u32] into r295 as [field; 3u32]; + cast 0field r1[1u32].siblings[5u32] r287 into r296 as [field; 3u32]; + ternary r294 r295[0u32] r296[0u32] into r297; + ternary r294 r295[1u32] r296[1u32] into r298; + ternary r294 r295[2u32] r296[2u32] into r299; + cast r297 r298 r299 into r300 as [field; 3u32]; + is.eq r1[1u32].siblings[5u32] 0field into r301; + hash.psd4 r300 into r302 as field; + ternary r301 r287 r302 into r303; + is.eq r1[1u32].siblings[6u32] 0field into r304; + is.eq r291 15u32 into r305; + and r304 r305 into r306; + ternary r306 5u32 r291 into r307; + div r1[1u32].leaf_index 32u32 into r308; + rem r308 2u32 into r309; + is.eq r309 0u32 into r310; + cast 0field r303 r1[1u32].siblings[6u32] into r311 as [field; 3u32]; + cast 0field r1[1u32].siblings[6u32] r303 into r312 as [field; 3u32]; + ternary r310 r311[0u32] r312[0u32] into r313; + ternary r310 r311[1u32] r312[1u32] into r314; + ternary r310 r311[2u32] r312[2u32] into r315; + cast r313 r314 r315 into r316 as [field; 3u32]; + is.eq r1[1u32].siblings[6u32] 0field into r317; + hash.psd4 r316 into r318 as field; + ternary r317 r303 r318 into r319; + is.eq r1[1u32].siblings[7u32] 0field into r320; + is.eq r307 15u32 into r321; + and r320 r321 into r322; + ternary r322 6u32 r307 into r323; + div r1[1u32].leaf_index 64u32 into r324; + rem r324 2u32 into r325; + is.eq r325 0u32 into r326; + cast 0field r319 r1[1u32].siblings[7u32] into r327 as [field; 3u32]; + cast 0field r1[1u32].siblings[7u32] r319 into r328 as [field; 3u32]; + ternary r326 r327[0u32] r328[0u32] into r329; + ternary r326 r327[1u32] r328[1u32] into r330; + ternary r326 r327[2u32] r328[2u32] into r331; + cast r329 r330 r331 into r332 as [field; 3u32]; + is.eq r1[1u32].siblings[7u32] 0field into r333; + hash.psd4 r332 into r334 as field; + ternary r333 r319 r334 into r335; + is.eq r1[1u32].siblings[8u32] 0field into r336; + is.eq r323 15u32 into r337; + and r336 r337 into r338; + ternary r338 7u32 r323 into r339; + div r1[1u32].leaf_index 128u32 into r340; + rem r340 2u32 into r341; + is.eq r341 0u32 into r342; + cast 0field r335 r1[1u32].siblings[8u32] into r343 as [field; 3u32]; + cast 0field r1[1u32].siblings[8u32] r335 into r344 as [field; 3u32]; + ternary r342 r343[0u32] r344[0u32] into r345; + ternary r342 r343[1u32] r344[1u32] into r346; + ternary r342 r343[2u32] r344[2u32] into r347; + cast r345 r346 r347 into r348 as [field; 3u32]; + is.eq r1[1u32].siblings[8u32] 0field into r349; + hash.psd4 r348 into r350 as field; + ternary r349 r335 r350 into r351; + is.eq r1[1u32].siblings[9u32] 0field into r352; + is.eq r339 15u32 into r353; + and r352 r353 into r354; + ternary r354 8u32 r339 into r355; + div r1[1u32].leaf_index 256u32 into r356; + rem r356 2u32 into r357; + is.eq r357 0u32 into r358; + cast 0field r351 r1[1u32].siblings[9u32] into r359 as [field; 3u32]; + cast 0field r1[1u32].siblings[9u32] r351 into r360 as [field; 3u32]; + ternary r358 r359[0u32] r360[0u32] into r361; + ternary r358 r359[1u32] r360[1u32] into r362; + ternary r358 r359[2u32] r360[2u32] into r363; + cast r361 r362 r363 into r364 as [field; 3u32]; + is.eq r1[1u32].siblings[9u32] 0field into r365; + hash.psd4 r364 into r366 as field; + ternary r365 r351 r366 into r367; + is.eq r1[1u32].siblings[10u32] 0field into r368; + is.eq r355 15u32 into r369; + and r368 r369 into r370; + ternary r370 9u32 r355 into r371; + div r1[1u32].leaf_index 512u32 into r372; + rem r372 2u32 into r373; + is.eq r373 0u32 into r374; + cast 0field r367 r1[1u32].siblings[10u32] into r375 as [field; 3u32]; + cast 0field r1[1u32].siblings[10u32] r367 into r376 as [field; 3u32]; + ternary r374 r375[0u32] r376[0u32] into r377; + ternary r374 r375[1u32] r376[1u32] into r378; + ternary r374 r375[2u32] r376[2u32] into r379; + cast r377 r378 r379 into r380 as [field; 3u32]; + is.eq r1[1u32].siblings[10u32] 0field into r381; + hash.psd4 r380 into r382 as field; + ternary r381 r367 r382 into r383; + is.eq r1[1u32].siblings[11u32] 0field into r384; + is.eq r371 15u32 into r385; + and r384 r385 into r386; + ternary r386 10u32 r371 into r387; + div r1[1u32].leaf_index 1024u32 into r388; + rem r388 2u32 into r389; + is.eq r389 0u32 into r390; + cast 0field r383 r1[1u32].siblings[11u32] into r391 as [field; 3u32]; + cast 0field r1[1u32].siblings[11u32] r383 into r392 as [field; 3u32]; + ternary r390 r391[0u32] r392[0u32] into r393; + ternary r390 r391[1u32] r392[1u32] into r394; + ternary r390 r391[2u32] r392[2u32] into r395; + cast r393 r394 r395 into r396 as [field; 3u32]; + is.eq r1[1u32].siblings[11u32] 0field into r397; + hash.psd4 r396 into r398 as field; + ternary r397 r383 r398 into r399; + is.eq r1[1u32].siblings[12u32] 0field into r400; + is.eq r387 15u32 into r401; + and r400 r401 into r402; + ternary r402 11u32 r387 into r403; + div r1[1u32].leaf_index 2048u32 into r404; + rem r404 2u32 into r405; + is.eq r405 0u32 into r406; + cast 0field r399 r1[1u32].siblings[12u32] into r407 as [field; 3u32]; + cast 0field r1[1u32].siblings[12u32] r399 into r408 as [field; 3u32]; + ternary r406 r407[0u32] r408[0u32] into r409; + ternary r406 r407[1u32] r408[1u32] into r410; + ternary r406 r407[2u32] r408[2u32] into r411; + cast r409 r410 r411 into r412 as [field; 3u32]; + is.eq r1[1u32].siblings[12u32] 0field into r413; + hash.psd4 r412 into r414 as field; + ternary r413 r399 r414 into r415; + is.eq r1[1u32].siblings[13u32] 0field into r416; + is.eq r403 15u32 into r417; + and r416 r417 into r418; + ternary r418 12u32 r403 into r419; + div r1[1u32].leaf_index 4096u32 into r420; + rem r420 2u32 into r421; + is.eq r421 0u32 into r422; + cast 0field r415 r1[1u32].siblings[13u32] into r423 as [field; 3u32]; + cast 0field r1[1u32].siblings[13u32] r415 into r424 as [field; 3u32]; + ternary r422 r423[0u32] r424[0u32] into r425; + ternary r422 r423[1u32] r424[1u32] into r426; + ternary r422 r423[2u32] r424[2u32] into r427; + cast r425 r426 r427 into r428 as [field; 3u32]; + is.eq r1[1u32].siblings[13u32] 0field into r429; + hash.psd4 r428 into r430 as field; + ternary r429 r415 r430 into r431; + is.eq r1[1u32].siblings[14u32] 0field into r432; + is.eq r419 15u32 into r433; + and r432 r433 into r434; + ternary r434 13u32 r419 into r435; + div r1[1u32].leaf_index 8192u32 into r436; + rem r436 2u32 into r437; + is.eq r437 0u32 into r438; + cast 0field r431 r1[1u32].siblings[14u32] into r439 as [field; 3u32]; + cast 0field r1[1u32].siblings[14u32] r431 into r440 as [field; 3u32]; + ternary r438 r439[0u32] r440[0u32] into r441; + ternary r438 r439[1u32] r440[1u32] into r442; + ternary r438 r439[2u32] r440[2u32] into r443; + cast r441 r442 r443 into r444 as [field; 3u32]; + is.eq r1[1u32].siblings[14u32] 0field into r445; + hash.psd4 r444 into r446 as field; + ternary r445 r431 r446 into r447; + is.eq r1[1u32].siblings[15u32] 0field into r448; + is.eq r435 15u32 into r449; + and r448 r449 into r450; + ternary r450 14u32 r435 into r451; + div r1[1u32].leaf_index 16384u32 into r452; + rem r452 2u32 into r453; + is.eq r453 0u32 into r454; + cast 0field r447 r1[1u32].siblings[15u32] into r455 as [field; 3u32]; + cast 0field r1[1u32].siblings[15u32] r447 into r456 as [field; 3u32]; + ternary r454 r455[0u32] r456[0u32] into r457; + ternary r454 r455[1u32] r456[1u32] into r458; + ternary r454 r455[2u32] r456[2u32] into r459; + cast r457 r458 r459 into r460 as [field; 3u32]; + is.eq r1[1u32].siblings[15u32] 0field into r461; + hash.psd4 r460 into r462 as field; + ternary r461 r447 r462 into r463; + assert.eq r232 r463; + assert.eq r220 r451; + cast r0 into r464 as field; + is.eq r1[0u32].leaf_index r1[1u32].leaf_index into r465; + is.eq r1[0u32].leaf_index 0u32 into r466; + lt r464 r1[0u32].siblings[0u32] into r467; + and r465 r466 into r468; + not r468 into r469; + or r467 r469 into r470; + assert.eq r470 true; + not r466 into r471; + pow 2u32 r220 into r472; + sub r472 1u32 into r473; + and r465 r471 into r474; + not r474 into r475; + is.eq r1[0u32].leaf_index r473 into r476; + or r476 r475 into r477; + assert.eq r477 true; + gt r464 r1[0u32].siblings[0u32] into r478; + or r478 r475 into r479; + assert.eq r479 true; + not r465 into r480; + gt r464 r1[0u32].siblings[0u32] into r481; + not r480 into r482; + or r481 r482 into r483; + assert.eq r483 true; + lt r464 r1[1u32].siblings[0u32] into r484; + or r484 r482 into r485; + assert.eq r485 true; + lte r1[1u32].leaf_index r473 into r486; + or r486 r482 into r487; + assert.eq r487 true; + add r1[0u32].leaf_index 1u32 into r488; + is.eq r488 r1[1u32].leaf_index into r489; + or r489 r482 into r490; + assert.eq r490 true; + output r232 as field; + +function transfer_private: + input r0 as address.private; + input r1 as u128.private; + input r2 as Token.record; + input r3 as [freezelist.aleo/MerkleProof; 2u32].private; + call verify_non_inclusion r2.owner r3 into r4; + sub r2.amount r1 into r5; + cast r2.owner r5 into r6 as Token.record; + cast r0 r1 into r7 as Token.record; + cast aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px r1 r2.owner r0 into r8 as ComplianceRecord.record; + async transfer_private r4 into r9; + output r8 as ComplianceRecord.record; + output r6 as Token.record; + output r7 as Token.record; + output r9 as compliant_token_template.aleo/transfer_private.future; + +finalize transfer_private: + input r0 as field.public; + contains pause__[false] into r1; + get.or_use pause__[false] false into r2; + ternary r1 r2 false into r3; + cast r1 r3 into r4 as Optional__ATAkdHctJwx; + assert.eq r4.is_some true; + assert.eq r4.val false; + get freezelist.aleo/freeze_list_root[1u8] into r5; + get freezelist.aleo/block_height_window[true] into r6; + is.neq r5 r0 into r7; + branch.eq r7 false to end_then_0_0; + get freezelist.aleo/freeze_list_root[2u8] into r8; + assert.eq r0 r8; + get freezelist.aleo/root_updated_height[true] into r9; + add r9 r6 into r10; + gt r10 block.height into r11; + assert.eq r11 true; + branch.eq true true to end_otherwise_0_1; + position end_then_0_0; + position end_otherwise_0_1; + +function transfer_private_to_public: + input r0 as address.public; + input r1 as u128.public; + input r2 as Token.record; + input r3 as [freezelist.aleo/MerkleProof; 2u32].private; + call verify_non_inclusion r2.owner r3 into r4; + sub r2.amount r1 into r5; + cast r2.owner r5 into r6 as Token.record; + cast aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px r1 r2.owner r0 into r7 as ComplianceRecord.record; + async transfer_private_to_public r4 r0 r1 into r8; + output r7 as ComplianceRecord.record; + output r6 as Token.record; + output r8 as compliant_token_template.aleo/transfer_private_to_public.future; + +finalize transfer_private_to_public: + input r0 as field.public; + input r1 as address.public; + input r2 as u128.public; + contains pause__[false] into r3; + get.or_use pause__[false] false into r4; + ternary r3 r4 false into r5; + cast r3 r5 into r6 as Optional__ATAkdHctJwx; + assert.eq r6.is_some true; + assert.eq r6.val false; + get freezelist.aleo/freeze_list_root[1u8] into r7; + get freezelist.aleo/block_height_window[true] into r8; + is.neq r7 r0 into r9; + branch.eq r9 false to end_then_0_0; + get freezelist.aleo/freeze_list_root[2u8] into r10; + assert.eq r0 r10; + get freezelist.aleo/root_updated_height[true] into r11; + add r11 r8 into r12; + gt r12 block.height into r13; + assert.eq r13 true; + branch.eq true true to end_otherwise_0_1; + position end_then_0_0; + position end_otherwise_0_1; + get.or_use freezelist.aleo/freeze_list[r1] false into r14; + assert.eq r14 false; + get.or_use balances[r1] 0u128 into r15; + add r15 r2 into r16; + set r16 into balances[r1]; + +function set_pause_status: + input r0 as boolean.private; + async set_pause_status self.caller r0 into r1; + output r1 as compliant_token_template.aleo/set_pause_status.future; + +finalize set_pause_status: + input r0 as address.public; + input r1 as boolean.public; + get address_to_role[r0] into r2; + and r2 4u16 into r3; + is.eq r3 4u16 into r4; + assert.eq r4 true; + set r1 into pause__[false]; + +function join: + input r0 as Token.record; + input r1 as Token.record; + assert.eq r0.owner r1.owner; + add r0.amount r1.amount into r2; + cast r0.owner r2 into r3 as Token.record; + output r3 as Token.record; + +function split: + input r0 as Token.record; + input r1 as u128.private; + cast r0.owner r1 into r2 as Token.record; + sub r0.amount r1 into r3; + cast r0.owner r3 into r4 as Token.record; + output r2 as Token.record; + output r4 as Token.record; + +view balance_of: + input r0 as address.public; + get.or_use balances[r0] 0u128 into r1; + output r1 as u128.public; + +view allowance: + input r0 as address.public; + input r1 as address.public; + cast r0 r1 into r2 as TokenAllowance; + get.or_use allowances[r2] 0u128 into r3; + output r3 as u128.public; + +view supply: + contains token_info__[false] into r0; + cast 0u128 0u128 0u8 0u128 0u128 into r1 as TokenInfo; + get.or_use token_info__[false] r1 into r2; + cast 0u128 0u128 0u8 0u128 0u128 into r3 as TokenInfo; + ternary r0 r2.name r3.name into r4; + ternary r0 r2.symbol r3.symbol into r5; + ternary r0 r2.decimals r3.decimals into r6; + ternary r0 r2.supply r3.supply into r7; + ternary r0 r2.max_supply r3.max_supply into r8; + cast r4 r5 r6 r7 r8 into r9 as TokenInfo; + cast r0 r9 into r10 as Optional__An66AtVsP75; + cast 0u128 0u128 0u8 0u128 0u128 into r11 as TokenInfo; + ternary r10.is_some r10.val.name r11.name into r12; + ternary r10.is_some r10.val.symbol r11.symbol into r13; + ternary r10.is_some r10.val.decimals r11.decimals into r14; + ternary r10.is_some r10.val.supply r11.supply into r15; + ternary r10.is_some r10.val.max_supply r11.max_supply into r16; + cast r12 r13 r14 r15 r16 into r17 as TokenInfo; + output r17.supply as u128.public; + +view max_supply: + contains token_info__[false] into r0; + cast 0u128 0u128 0u8 0u128 0u128 into r1 as TokenInfo; + get.or_use token_info__[false] r1 into r2; + cast 0u128 0u128 0u8 0u128 0u128 into r3 as TokenInfo; + ternary r0 r2.name r3.name into r4; + ternary r0 r2.symbol r3.symbol into r5; + ternary r0 r2.decimals r3.decimals into r6; + ternary r0 r2.supply r3.supply into r7; + ternary r0 r2.max_supply r3.max_supply into r8; + cast r4 r5 r6 r7 r8 into r9 as TokenInfo; + cast r0 r9 into r10 as Optional__An66AtVsP75; + cast 0u128 0u128 0u8 0u128 0u128 into r11 as TokenInfo; + ternary r10.is_some r10.val.name r11.name into r12; + ternary r10.is_some r10.val.symbol r11.symbol into r13; + ternary r10.is_some r10.val.decimals r11.decimals into r14; + ternary r10.is_some r10.val.supply r11.supply into r15; + ternary r10.is_some r10.val.max_supply r11.max_supply into r16; + cast r12 r13 r14 r15 r16 into r17 as TokenInfo; + output r17.max_supply as u128.public; + +view decimals: + contains token_info__[false] into r0; + cast 0u128 0u128 0u8 0u128 0u128 into r1 as TokenInfo; + get.or_use token_info__[false] r1 into r2; + cast 0u128 0u128 0u8 0u128 0u128 into r3 as TokenInfo; + ternary r0 r2.name r3.name into r4; + ternary r0 r2.symbol r3.symbol into r5; + ternary r0 r2.decimals r3.decimals into r6; + ternary r0 r2.supply r3.supply into r7; + ternary r0 r2.max_supply r3.max_supply into r8; + cast r4 r5 r6 r7 r8 into r9 as TokenInfo; + cast r0 r9 into r10 as Optional__An66AtVsP75; + cast 0u128 0u128 0u8 0u128 0u128 into r11 as TokenInfo; + ternary r10.is_some r10.val.name r11.name into r12; + ternary r10.is_some r10.val.symbol r11.symbol into r13; + ternary r10.is_some r10.val.decimals r11.decimals into r14; + ternary r10.is_some r10.val.supply r11.supply into r15; + ternary r10.is_some r10.val.max_supply r11.max_supply into r16; + cast r12 r13 r14 r15 r16 into r17 as TokenInfo; + output r17.decimals as u8.public; + +view name: + output 'CompliantToken' as identifier.public; + +view symbol: + output 'COMP' as identifier.public; + +constructor: + gt edition 0u16 into r0; + branch.eq r0 false to end_then_0_0; + cast checksum edition into r1 as ChecksumEdition; + hash.bhp256 r1 into r2 as field; + cast compliant_token_template.aleo r2 into r3 as multisig_core.aleo/WalletSigningOpId; + hash.bhp256 r3 into r4 as field; + contains multisig_core.aleo/completed_signing_ops[r4] into r5; + assert.eq r5 true; + branch.eq true true to end_otherwise_0_1; + position end_then_0_0; + position end_otherwise_0_1; diff --git a/sdk/python/tests/fixtures/test_arc20_eth.aleo b/sdk/python/tests/fixtures/test_arc20_eth.aleo new file mode 100644 index 0000000..b27ad5f --- /dev/null +++ b/sdk/python/tests/fixtures/test_arc20_eth.aleo @@ -0,0 +1,483 @@ +import test_arc20_multisig_core.aleo; + +program test_arc20_eth.aleo; + +record Token: + owner as address.private; + amount as u128.private; + +struct ChecksumEdition: + checksum as [u8; 32u32]; + edition as u16; + +struct TokenAllowance: + account as address; + spender as address; + +struct Optional__6A9ZdhLQa8N: + is_some as boolean; + val as u128; + +mapping address_to_role: + key as address.public; + value as u16.public; + +mapping allowances: + key as field.public; + value as u128.public; + +mapping balances: + key as address.public; + value as u128.public; + +mapping pause: + key as boolean.public; + value as boolean.public; + +mapping initialized: + key as boolean.public; + value as boolean.public; + +mapping token_supply__: + key as boolean.public; + value as u128.public; + +function approve_public: + input r0 as address.public; + input r1 as u128.public; + cast self.caller r0 into r2 as TokenAllowance; + hash.bhp256 r2 into r3 as field; + async approve_public r3 r1 into r4; + output r4 as test_arc20_eth.aleo/approve_public.future; + +finalize approve_public: + input r0 as field.public; + input r1 as u128.public; + get.or_use allowances[r0] 0u128 into r2; + add r2 r1 into r3; + set r3 into allowances[r0]; + +function unapprove_public: + input r0 as address.public; + input r1 as u128.public; + cast self.caller r0 into r2 as TokenAllowance; + hash.bhp256 r2 into r3 as field; + async unapprove_public r3 r1 into r4; + output r4 as test_arc20_eth.aleo/unapprove_public.future; + +finalize unapprove_public: + input r0 as field.public; + input r1 as u128.public; + get.or_use allowances[r0] 0u128 into r2; + gte r2 r1 into r3; + assert.eq r3 true; + sub r2 r1 into r4; + set r4 into allowances[r0]; + +function transfer_public: + input r0 as address.public; + input r1 as u128.public; + async transfer_public self.caller r1 r0 into r2; + output r2 as test_arc20_eth.aleo/transfer_public.future; + +finalize transfer_public: + input r0 as address.public; + input r1 as u128.public; + input r2 as address.public; + get.or_use balances[r0] 0u128 into r3; + gte r3 r1 into r4; + assert.eq r4 true; + sub r3 r1 into r5; + set r5 into balances[r0]; + get.or_use balances[r2] 0u128 into r6; + add r6 r1 into r7; + set r7 into balances[r2]; + +function transfer_public_as_signer: + input r0 as address.public; + input r1 as u128.public; + async transfer_public_as_signer self.signer r1 r0 into r2; + output r2 as test_arc20_eth.aleo/transfer_public_as_signer.future; + +finalize transfer_public_as_signer: + input r0 as address.public; + input r1 as u128.public; + input r2 as address.public; + get.or_use balances[r0] 0u128 into r3; + gte r3 r1 into r4; + assert.eq r4 true; + sub r3 r1 into r5; + set r5 into balances[r0]; + get.or_use balances[r2] 0u128 into r6; + add r6 r1 into r7; + set r7 into balances[r2]; + +function transfer_private: + input r0 as Token.record; + input r1 as address.private; + input r2 as u128.private; + sub r0.amount r2 into r3; + cast r0.owner r3 into r4 as Token.record; + cast r1 r2 into r5 as Token.record; + output r4 as Token.record; + output r5 as Token.record; + +function transfer_private_to_public: + input r0 as Token.record; + input r1 as address.public; + input r2 as u128.public; + sub r0.amount r2 into r3; + cast r0.owner r3 into r4 as Token.record; + async transfer_private_to_public r1 r2 into r5; + output r4 as Token.record; + output r5 as test_arc20_eth.aleo/transfer_private_to_public.future; + +finalize transfer_private_to_public: + input r0 as address.public; + input r1 as u128.public; + get.or_use balances[r0] 0u128 into r2; + add r2 r1 into r3; + set r3 into balances[r0]; + +function transfer_public_to_private: + input r0 as address.private; + input r1 as u128.public; + cast r0 r1 into r2 as Token.record; + async transfer_public_to_private self.caller r1 into r3; + output r2 as Token.record; + output r3 as test_arc20_eth.aleo/transfer_public_to_private.future; + +finalize transfer_public_to_private: + input r0 as address.public; + input r1 as u128.public; + get.or_use balances[r0] 0u128 into r2; + gte r2 r1 into r3; + assert.eq r3 true; + sub r2 r1 into r4; + set r4 into balances[r0]; + +function transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r0 self.caller into r3 as TokenAllowance; + hash.bhp256 r3 into r4 as field; + async transfer_from_public r4 r2 r0 r1 into r5; + output r5 as test_arc20_eth.aleo/transfer_from_public.future; + +finalize transfer_from_public: + input r0 as field.public; + input r1 as u128.public; + input r2 as address.public; + input r3 as address.public; + get.or_use allowances[r0] 0u128 into r4; + gte r4 r1 into r5; + assert.eq r5 true; + sub r4 r1 into r6; + set r6 into allowances[r0]; + get.or_use balances[r2] 0u128 into r7; + gte r7 r1 into r8; + assert.eq r8 true; + sub r7 r1 into r9; + set r9 into balances[r2]; + get.or_use balances[r3] 0u128 into r10; + add r10 r1 into r11; + set r11 into balances[r3]; + +function transfer_from_public_to_private: + input r0 as address.public; + input r1 as address.private; + input r2 as u128.public; + cast r0 self.caller into r3 as TokenAllowance; + hash.bhp256 r3 into r4 as field; + cast r1 r2 into r5 as Token.record; + async transfer_from_public_to_private r4 r2 r0 into r6; + output r5 as Token.record; + output r6 as test_arc20_eth.aleo/transfer_from_public_to_private.future; + +finalize transfer_from_public_to_private: + input r0 as field.public; + input r1 as u128.public; + input r2 as address.public; + get.or_use allowances[r0] 0u128 into r3; + gte r3 r1 into r4; + assert.eq r4 true; + sub r3 r1 into r5; + set r5 into allowances[r0]; + get.or_use balances[r2] 0u128 into r6; + gte r6 r1 into r7; + assert.eq r7 true; + sub r6 r1 into r8; + set r8 into balances[r2]; + +function shield: + input r0 as u128.public; + cast self.caller r0 into r1 as Token.record; + async shield self.caller r0 into r2; + output r1 as Token.record; + output r2 as test_arc20_eth.aleo/shield.future; + +finalize shield: + input r0 as address.public; + input r1 as u128.public; + get.or_use balances[r0] 0u128 into r2; + gte r2 r1 into r3; + assert.eq r3 true; + sub r2 r1 into r4; + set r4 into balances[r0]; + +function unshield: + input r0 as Token.record; + input r1 as u128.private; + sub r0.amount r1 into r2; + cast r0.owner r2 into r3 as Token.record; + async unshield r0.owner r1 into r4; + output r3 as Token.record; + output r4 as test_arc20_eth.aleo/unshield.future; + +finalize unshield: + input r0 as address.public; + input r1 as u128.public; + get.or_use balances[r0] 0u128 into r2; + add r2 r1 into r3; + set r3 into balances[r0]; + +function join: + input r0 as Token.record; + input r1 as Token.record; + is.eq r0.owner r1.owner into r2; + assert.eq r2 true; + add r0.amount r1.amount into r3; + cast r0.owner r3 into r4 as Token.record; + output r4 as Token.record; + +function split: + input r0 as Token.record; + input r1 as u128.private; + cast r0.owner r1 into r2 as Token.record; + sub r0.amount r1 into r3; + cast r0.owner r3 into r4 as Token.record; + output r2 as Token.record; + output r4 as Token.record; + +function mint_public: + input r0 as address.public; + input r1 as u128.public; + async mint_public self.caller r0 r1 into r2; + output r2 as test_arc20_eth.aleo/mint_public.future; + +finalize mint_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get address_to_role[r0] into r3; + and r3 1u16 into r4; + is.eq r4 1u16 into r5; + assert.eq r5 true; + get.or_use pause[true] false into r6; + assert.eq r6 false; + get.or_use balances[r1] 0u128 into r7; + add r2 r7 into r8; + set r8 into balances[r1]; + contains token_supply__[false] into r9; + get.or_use token_supply__[false] 0u128 into r10; + ternary r9 r10 0u128 into r11; + cast r9 r11 into r12 as Optional__6A9ZdhLQa8N; + ternary r12.is_some r12.val 0u128 into r13; + add r13 r2 into r14; + lte r14 340282366920938463463374607431768211455u128 into r15; + assert.eq r15 true; + set r14 into token_supply__[false]; + +function mint_private: + input r0 as address.private; + input r1 as u128.private; + cast r0 r1 into r2 as Token.record; + async mint_private self.caller r1 into r3; + output r2 as Token.record; + output r3 as test_arc20_eth.aleo/mint_private.future; + +finalize mint_private: + input r0 as address.public; + input r1 as u128.public; + get address_to_role[r0] into r2; + and r2 1u16 into r3; + is.eq r3 1u16 into r4; + assert.eq r4 true; + get.or_use pause[true] false into r5; + assert.eq r5 false; + contains token_supply__[false] into r6; + get.or_use token_supply__[false] 0u128 into r7; + ternary r6 r7 0u128 into r8; + cast r6 r8 into r9 as Optional__6A9ZdhLQa8N; + ternary r9.is_some r9.val 0u128 into r10; + add r10 r1 into r11; + lte r11 340282366920938463463374607431768211455u128 into r12; + assert.eq r12 true; + set r11 into token_supply__[false]; + +function burn_public: + input r0 as address.public; + input r1 as u128.public; + async burn_public self.caller r0 r1 into r2; + output r2 as test_arc20_eth.aleo/burn_public.future; + +finalize burn_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + get address_to_role[r0] into r3; + and r3 2u16 into r4; + is.eq r4 2u16 into r5; + assert.eq r5 true; + get.or_use pause[true] false into r6; + assert.eq r6 false; + get.or_use balances[r1] 0u128 into r7; + gte r7 r2 into r8; + assert.eq r8 true; + sub r7 r2 into r9; + set r9 into balances[r1]; + contains token_supply__[false] into r10; + get.or_use token_supply__[false] 0u128 into r11; + ternary r10 r11 0u128 into r12; + cast r10 r12 into r13 as Optional__6A9ZdhLQa8N; + ternary r13.is_some r13.val 0u128 into r14; + gte r14 r2 into r15; + assert.eq r15 true; + sub r14 r2 into r16; + set r16 into token_supply__[false]; + +function burn_private: + input r0 as Token.record; + input r1 as u128.private; + sub r0.amount r1 into r2; + cast r0.owner r2 into r3 as Token.record; + async burn_private self.caller r1 into r4; + output r3 as Token.record; + output r4 as test_arc20_eth.aleo/burn_private.future; + +finalize burn_private: + input r0 as address.public; + input r1 as u128.public; + get address_to_role[r0] into r2; + and r2 2u16 into r3; + is.eq r3 2u16 into r4; + assert.eq r4 true; + get.or_use pause[true] false into r5; + assert.eq r5 false; + contains token_supply__[false] into r6; + get.or_use token_supply__[false] 0u128 into r7; + ternary r6 r7 0u128 into r8; + cast r6 r8 into r9 as Optional__6A9ZdhLQa8N; + ternary r9.is_some r9.val 0u128 into r10; + gte r10 r1 into r11; + assert.eq r11 true; + sub r10 r1 into r12; + set r12 into token_supply__[false]; + +function initialize_token: + input r0 as address.private; + is.eq self.caller aleo1axurgcdhztu8m23ttzju38qzchtzs8kyk7nga9n58zyrmnxzmuqqf6wqdc into r1; + assert.eq r1 true; + async initialize_token r0 into r2; + output r2 as test_arc20_eth.aleo/initialize_token.future; + +finalize initialize_token: + input r0 as address.public; + get.or_use initialized[true] false into r1; + assert.eq r1 false; + set 0u128 into token_supply__[false]; + set 8u16 into address_to_role[r0]; + set true into initialized[true]; + +function update_role: + input r0 as address.public; + input r1 as u16.private; + async update_role self.caller r0 r1 into r2; + output r2 as test_arc20_eth.aleo/update_role.future; + +finalize update_role: + input r0 as address.public; + input r1 as address.public; + input r2 as u16.public; + get address_to_role[r0] into r3; + and r3 8u16 into r4; + is.eq r4 8u16 into r5; + assert.eq r5 true; + is.eq r0 r1 into r6; + branch.eq r6 false to end_then_0_0; + and r2 8u16 into r7; + is.eq r7 8u16 into r8; + assert.eq r8 true; + branch.eq true true to end_otherwise_0_1; + position end_then_0_0; + position end_otherwise_0_1; + set r2 into address_to_role[r1]; + +function set_pause_status: + input r0 as boolean.public; + async set_pause_status self.caller r0 into r1; + output r1 as test_arc20_eth.aleo/set_pause_status.future; + +finalize set_pause_status: + input r0 as address.public; + input r1 as boolean.public; + get address_to_role[r0] into r2; + and r2 4u16 into r3; + is.eq r3 4u16 into r4; + assert.eq r4 true; + set r1 into pause[true]; + +view balance_of: + input r0 as address.public; + get.or_use balances[r0] 0u128 into r1; + output r1 as u128.public; + +view allowance: + input r0 as address.public; + input r1 as address.public; + cast r0 r1 into r2 as TokenAllowance; + hash.bhp256 r2 into r3 as field; + get.or_use allowances[r3] 0u128 into r4; + output r4 as u128.public; + +view supply: + contains token_supply__[false] into r0; + get.or_use token_supply__[false] 0u128 into r1; + ternary r0 r1 0u128 into r2; + cast r0 r2 into r3 as Optional__6A9ZdhLQa8N; + ternary r3.is_some r3.val 0u128 into r4; + output r4 as u128.public; + +view max_supply: + output 340282366920938463463374607431768211455u128 as u128.public; + +view decimals: + output 18u8 as u8.public; + +view name: + output 'ETH' as identifier.public; + +view symbol: + output 'ETH' as identifier.public; + +constructor: + cast 84u8 67u8 183u8 135u8 190u8 112u8 42u8 231u8 139u8 206u8 43u8 239u8 194u8 229u8 201u8 56u8 247u8 3u8 223u8 218u8 46u8 226u8 170u8 52u8 45u8 146u8 157u8 238u8 134u8 20u8 2u8 13u8 into r0 as [u8; 32u32]; + assert.eq name/checksum r0; + cast 116u8 97u8 51u8 116u8 62u8 23u8 247u8 9u8 190u8 233u8 13u8 220u8 45u8 79u8 149u8 158u8 103u8 29u8 158u8 190u8 152u8 171u8 222u8 32u8 90u8 139u8 103u8 55u8 184u8 71u8 253u8 83u8 into r1 as [u8; 32u32]; + assert.eq symbol/checksum r1; + cast 104u8 146u8 24u8 45u8 88u8 124u8 174u8 91u8 215u8 92u8 141u8 129u8 22u8 44u8 189u8 73u8 205u8 217u8 240u8 3u8 219u8 72u8 253u8 79u8 222u8 15u8 28u8 79u8 6u8 28u8 239u8 219u8 into r2 as [u8; 32u32]; + assert.eq decimals/checksum r2; + cast 205u8 178u8 247u8 132u8 253u8 223u8 249u8 127u8 47u8 226u8 176u8 159u8 28u8 113u8 162u8 63u8 192u8 245u8 28u8 142u8 229u8 97u8 243u8 122u8 9u8 163u8 70u8 84u8 253u8 150u8 63u8 127u8 into r3 as [u8; 32u32]; + assert.eq max_supply/checksum r3; + gt edition 0u16 into r4; + branch.eq r4 false to end_then_0_0; + cast checksum edition into r5 as ChecksumEdition; + hash.bhp256 r5 into r6 as field; + cast test_arc20_eth.aleo r6 into r7 as test_arc20_multisig_core.aleo/WalletSigningOpId; + hash.bhp256 r7 into r8 as field; + contains test_arc20_multisig_core.aleo/completed_signing_ops[r8] into r9; + assert.eq r9 true; + branch.eq true true to end_otherwise_0_1; + position end_then_0_0; + position end_otherwise_0_1; diff --git a/sdk/python/tests/fixtures/test_usdcx_stablecoin.aleo b/sdk/python/tests/fixtures/test_usdcx_stablecoin.aleo new file mode 100644 index 0000000..c7c816c --- /dev/null +++ b/sdk/python/tests/fixtures/test_usdcx_stablecoin.aleo @@ -0,0 +1,1833 @@ +import merkle_tree.aleo; +import test_usdcx_multisig_core.aleo; +import test_usdcx_freezelist.aleo; + +program test_usdcx_stablecoin.aleo; + +record Token: + owner as address.private; + amount as u128.private; + +record ComplianceRecord: + owner as address.private; + amount as u128.private; + sender as address.private; + recipient as address.private; + +record Credentials: + owner as address.private; + freeze_list_root as field.private; + +struct ChecksumEdition: + checksum as [u8; 32u32]; + edition as u16; + +struct TokenInfo: + name as u128; + symbol as u128; + decimals as u8; + supply as u128; + max_supply as u128; + +struct TokenAllowance: + account as address; + spender as address; + +struct MerkleProof: + siblings as [field; 16u32]; + leaf_index as u32; + +struct WalletEcdsaSigner: + wallet_id as address; + ecdsa_signer as [u8; 20u32]; + +struct WalletSigningOpId: + wallet_id as address; + signing_op_id as field; + +struct AdminOp: + op as u8; + threshold as u8; + aleo_signer as address; + ecdsa_signer as [u8; 20u32]; + +mapping token_info: + key as boolean.public; + value as TokenInfo.public; + +mapping balances: + key as address.public; + value as u128.public; + +mapping allowances: + key as field.public; + value as u128.public; + +mapping address_to_role: + key as address.public; + value as u16.public; + +mapping pause: + key as boolean.public; + value as boolean.public; + +function get_signing_op_id_for_deploy: + input r0 as [u8; 32u32].private; + input r1 as u16.private; + cast r0 r1 into r2 as ChecksumEdition; + hash.bhp256 r2 into r3 as field; + output r3 as field.private; + +function update_role: + input r0 as address.public; + input r1 as u16.private; + async update_role r0 self.caller r1 into r2; + output r2 as test_usdcx_stablecoin.aleo/update_role.future; + +finalize update_role: + input r0 as address.public; + input r1 as address.public; + input r2 as u16.public; + get address_to_role[r1] into r3; + and r3 8u16 into r4; + is.eq r4 8u16 into r5; + assert.eq r5 true; + is.eq r1 r0 into r6; + branch.eq r6 false to end_then_0_0; + and r2 8u16 into r7; + is.eq r7 8u16 into r8; + assert.eq r8 true; + branch.eq true true to end_otherwise_0_1; + position end_then_0_0; + position end_otherwise_0_1; + set r2 into address_to_role[r0]; + +function initialize: + input r0 as u128.public; + input r1 as u128.public; + input r2 as u8.public; + input r3 as u128.public; + input r4 as address.public; + async initialize r0 r1 r2 r3 r4 self.caller into r5; + output r5 as test_usdcx_stablecoin.aleo/initialize.future; + +finalize initialize: + input r0 as u128.public; + input r1 as u128.public; + input r2 as u8.public; + input r3 as u128.public; + input r4 as address.public; + input r5 as address.public; + contains token_info[true] into r6; + assert.eq r6 false; + assert.eq r5 aleo17pmtmh8t7zwh0qfj8z0cmg0rqt4rtg4t85dy5ldrst5u0c4yvufq3gl9lf; + set 8u16 into address_to_role[r4]; + cast r0 r1 r2 0u128 r3 into r7 as TokenInfo; + set r7 into token_info[true]; + set false into pause[true]; + +function get_credentials: + input r0 as [MerkleProof; 2u32].private; + rem r0[0u32].leaf_index 2u32 into r1; + is.eq r1 0u32 into r2; + cast 1field r0[0u32].siblings[0u32] r0[0u32].siblings[1u32] into r3 as [field; 3u32]; + cast 1field r0[0u32].siblings[1u32] r0[0u32].siblings[0u32] into r4 as [field; 3u32]; + ternary r2 r3[0u32] r4[0u32] into r5; + ternary r2 r3[1u32] r4[1u32] into r6; + ternary r2 r3[2u32] r4[2u32] into r7; + cast r5 r6 r7 into r8 as [field; 3u32]; + hash.psd4 r8 into r9 as field; + is.eq r0[0u32].siblings[2u32] 0field into r10; + div r0[0u32].leaf_index 2u32 into r11; + rem r11 2u32 into r12; + is.eq r12 0u32 into r13; + cast 0field r9 r0[0u32].siblings[2u32] into r14 as [field; 3u32]; + cast 0field r0[0u32].siblings[2u32] r9 into r15 as [field; 3u32]; + ternary r13 r14[0u32] r15[0u32] into r16; + ternary r13 r14[1u32] r15[1u32] into r17; + ternary r13 r14[2u32] r15[2u32] into r18; + cast r16 r17 r18 into r19 as [field; 3u32]; + hash.psd4 r19 into r20 as field; + is.eq r0[0u32].siblings[3u32] 0field into r21; + div r0[0u32].leaf_index 4u32 into r22; + rem r22 2u32 into r23; + is.eq r23 0u32 into r24; + cast 0field r20 r0[0u32].siblings[3u32] into r25 as [field; 3u32]; + cast 0field r0[0u32].siblings[3u32] r20 into r26 as [field; 3u32]; + ternary r24 r25[0u32] r26[0u32] into r27; + ternary r24 r25[1u32] r26[1u32] into r28; + ternary r24 r25[2u32] r26[2u32] into r29; + cast r27 r28 r29 into r30 as [field; 3u32]; + hash.psd4 r30 into r31 as field; + is.eq r0[0u32].siblings[4u32] 0field into r32; + div r0[0u32].leaf_index 8u32 into r33; + rem r33 2u32 into r34; + is.eq r34 0u32 into r35; + cast 0field r31 r0[0u32].siblings[4u32] into r36 as [field; 3u32]; + cast 0field r0[0u32].siblings[4u32] r31 into r37 as [field; 3u32]; + ternary r35 r36[0u32] r37[0u32] into r38; + ternary r35 r36[1u32] r37[1u32] into r39; + ternary r35 r36[2u32] r37[2u32] into r40; + cast r38 r39 r40 into r41 as [field; 3u32]; + hash.psd4 r41 into r42 as field; + is.eq r0[0u32].siblings[5u32] 0field into r43; + div r0[0u32].leaf_index 16u32 into r44; + rem r44 2u32 into r45; + is.eq r45 0u32 into r46; + cast 0field r42 r0[0u32].siblings[5u32] into r47 as [field; 3u32]; + cast 0field r0[0u32].siblings[5u32] r42 into r48 as [field; 3u32]; + ternary r46 r47[0u32] r48[0u32] into r49; + ternary r46 r47[1u32] r48[1u32] into r50; + ternary r46 r47[2u32] r48[2u32] into r51; + cast r49 r50 r51 into r52 as [field; 3u32]; + hash.psd4 r52 into r53 as field; + is.eq r0[0u32].siblings[6u32] 0field into r54; + div r0[0u32].leaf_index 32u32 into r55; + rem r55 2u32 into r56; + is.eq r56 0u32 into r57; + cast 0field r53 r0[0u32].siblings[6u32] into r58 as [field; 3u32]; + cast 0field r0[0u32].siblings[6u32] r53 into r59 as [field; 3u32]; + ternary r57 r58[0u32] r59[0u32] into r60; + ternary r57 r58[1u32] r59[1u32] into r61; + ternary r57 r58[2u32] r59[2u32] into r62; + cast r60 r61 r62 into r63 as [field; 3u32]; + hash.psd4 r63 into r64 as field; + is.eq r0[0u32].siblings[7u32] 0field into r65; + div r0[0u32].leaf_index 64u32 into r66; + rem r66 2u32 into r67; + is.eq r67 0u32 into r68; + cast 0field r64 r0[0u32].siblings[7u32] into r69 as [field; 3u32]; + cast 0field r0[0u32].siblings[7u32] r64 into r70 as [field; 3u32]; + ternary r68 r69[0u32] r70[0u32] into r71; + ternary r68 r69[1u32] r70[1u32] into r72; + ternary r68 r69[2u32] r70[2u32] into r73; + cast r71 r72 r73 into r74 as [field; 3u32]; + hash.psd4 r74 into r75 as field; + is.eq r0[0u32].siblings[8u32] 0field into r76; + div r0[0u32].leaf_index 128u32 into r77; + rem r77 2u32 into r78; + is.eq r78 0u32 into r79; + cast 0field r75 r0[0u32].siblings[8u32] into r80 as [field; 3u32]; + cast 0field r0[0u32].siblings[8u32] r75 into r81 as [field; 3u32]; + ternary r79 r80[0u32] r81[0u32] into r82; + ternary r79 r80[1u32] r81[1u32] into r83; + ternary r79 r80[2u32] r81[2u32] into r84; + cast r82 r83 r84 into r85 as [field; 3u32]; + hash.psd4 r85 into r86 as field; + is.eq r0[0u32].siblings[9u32] 0field into r87; + div r0[0u32].leaf_index 256u32 into r88; + rem r88 2u32 into r89; + is.eq r89 0u32 into r90; + cast 0field r86 r0[0u32].siblings[9u32] into r91 as [field; 3u32]; + cast 0field r0[0u32].siblings[9u32] r86 into r92 as [field; 3u32]; + ternary r90 r91[0u32] r92[0u32] into r93; + ternary r90 r91[1u32] r92[1u32] into r94; + ternary r90 r91[2u32] r92[2u32] into r95; + cast r93 r94 r95 into r96 as [field; 3u32]; + hash.psd4 r96 into r97 as field; + is.eq r0[0u32].siblings[10u32] 0field into r98; + div r0[0u32].leaf_index 512u32 into r99; + rem r99 2u32 into r100; + is.eq r100 0u32 into r101; + cast 0field r97 r0[0u32].siblings[10u32] into r102 as [field; 3u32]; + cast 0field r0[0u32].siblings[10u32] r97 into r103 as [field; 3u32]; + ternary r101 r102[0u32] r103[0u32] into r104; + ternary r101 r102[1u32] r103[1u32] into r105; + ternary r101 r102[2u32] r103[2u32] into r106; + cast r104 r105 r106 into r107 as [field; 3u32]; + hash.psd4 r107 into r108 as field; + is.eq r0[0u32].siblings[11u32] 0field into r109; + div r0[0u32].leaf_index 1024u32 into r110; + rem r110 2u32 into r111; + is.eq r111 0u32 into r112; + cast 0field r108 r0[0u32].siblings[11u32] into r113 as [field; 3u32]; + cast 0field r0[0u32].siblings[11u32] r108 into r114 as [field; 3u32]; + ternary r112 r113[0u32] r114[0u32] into r115; + ternary r112 r113[1u32] r114[1u32] into r116; + ternary r112 r113[2u32] r114[2u32] into r117; + cast r115 r116 r117 into r118 as [field; 3u32]; + hash.psd4 r118 into r119 as field; + is.eq r0[0u32].siblings[12u32] 0field into r120; + div r0[0u32].leaf_index 2048u32 into r121; + rem r121 2u32 into r122; + is.eq r122 0u32 into r123; + cast 0field r119 r0[0u32].siblings[12u32] into r124 as [field; 3u32]; + cast 0field r0[0u32].siblings[12u32] r119 into r125 as [field; 3u32]; + ternary r123 r124[0u32] r125[0u32] into r126; + ternary r123 r124[1u32] r125[1u32] into r127; + ternary r123 r124[2u32] r125[2u32] into r128; + cast r126 r127 r128 into r129 as [field; 3u32]; + hash.psd4 r129 into r130 as field; + is.eq r0[0u32].siblings[13u32] 0field into r131; + div r0[0u32].leaf_index 4096u32 into r132; + rem r132 2u32 into r133; + is.eq r133 0u32 into r134; + cast 0field r130 r0[0u32].siblings[13u32] into r135 as [field; 3u32]; + cast 0field r0[0u32].siblings[13u32] r130 into r136 as [field; 3u32]; + ternary r134 r135[0u32] r136[0u32] into r137; + ternary r134 r135[1u32] r136[1u32] into r138; + ternary r134 r135[2u32] r136[2u32] into r139; + cast r137 r138 r139 into r140 as [field; 3u32]; + hash.psd4 r140 into r141 as field; + is.eq r0[0u32].siblings[14u32] 0field into r142; + div r0[0u32].leaf_index 8192u32 into r143; + rem r143 2u32 into r144; + is.eq r144 0u32 into r145; + cast 0field r141 r0[0u32].siblings[14u32] into r146 as [field; 3u32]; + cast 0field r0[0u32].siblings[14u32] r141 into r147 as [field; 3u32]; + ternary r145 r146[0u32] r147[0u32] into r148; + ternary r145 r146[1u32] r147[1u32] into r149; + ternary r145 r146[2u32] r147[2u32] into r150; + cast r148 r149 r150 into r151 as [field; 3u32]; + hash.psd4 r151 into r152 as field; + is.eq r0[0u32].siblings[15u32] 0field into r153; + div r0[0u32].leaf_index 16384u32 into r154; + rem r154 2u32 into r155; + is.eq r155 0u32 into r156; + cast 0field r152 r0[0u32].siblings[15u32] into r157 as [field; 3u32]; + cast 0field r0[0u32].siblings[15u32] r152 into r158 as [field; 3u32]; + ternary r156 r157[0u32] r158[0u32] into r159; + ternary r156 r157[1u32] r158[1u32] into r160; + ternary r156 r157[2u32] r158[2u32] into r161; + cast r159 r160 r161 into r162 as [field; 3u32]; + hash.psd4 r162 into r163 as field; + ternary r153 r152 r163 into r164; + ternary r153 14u32 15u32 into r165; + ternary r142 r141 r164 into r166; + ternary r142 13u32 r165 into r167; + ternary r131 r130 r166 into r168; + ternary r131 12u32 r167 into r169; + ternary r120 r119 r168 into r170; + ternary r120 11u32 r169 into r171; + ternary r109 r108 r170 into r172; + ternary r109 10u32 r171 into r173; + ternary r98 r97 r172 into r174; + ternary r98 9u32 r173 into r175; + ternary r87 r86 r174 into r176; + ternary r87 8u32 r175 into r177; + ternary r76 r75 r176 into r178; + ternary r76 7u32 r177 into r179; + ternary r65 r64 r178 into r180; + ternary r65 6u32 r179 into r181; + ternary r54 r53 r180 into r182; + ternary r54 5u32 r181 into r183; + ternary r43 r42 r182 into r184; + ternary r43 4u32 r183 into r185; + ternary r32 r31 r184 into r186; + ternary r32 3u32 r185 into r187; + ternary r21 r20 r186 into r188; + ternary r21 2u32 r187 into r189; + ternary r10 r9 r188 into r190; + ternary r10 1u32 r189 into r191; + rem r0[1u32].leaf_index 2u32 into r192; + is.eq r192 0u32 into r193; + cast 1field r0[1u32].siblings[0u32] r0[1u32].siblings[1u32] into r194 as [field; 3u32]; + cast 1field r0[1u32].siblings[1u32] r0[1u32].siblings[0u32] into r195 as [field; 3u32]; + ternary r193 r194[0u32] r195[0u32] into r196; + ternary r193 r194[1u32] r195[1u32] into r197; + ternary r193 r194[2u32] r195[2u32] into r198; + cast r196 r197 r198 into r199 as [field; 3u32]; + hash.psd4 r199 into r200 as field; + is.eq r0[1u32].siblings[2u32] 0field into r201; + div r0[1u32].leaf_index 2u32 into r202; + rem r202 2u32 into r203; + is.eq r203 0u32 into r204; + cast 0field r200 r0[1u32].siblings[2u32] into r205 as [field; 3u32]; + cast 0field r0[1u32].siblings[2u32] r200 into r206 as [field; 3u32]; + ternary r204 r205[0u32] r206[0u32] into r207; + ternary r204 r205[1u32] r206[1u32] into r208; + ternary r204 r205[2u32] r206[2u32] into r209; + cast r207 r208 r209 into r210 as [field; 3u32]; + hash.psd4 r210 into r211 as field; + is.eq r0[1u32].siblings[3u32] 0field into r212; + div r0[1u32].leaf_index 4u32 into r213; + rem r213 2u32 into r214; + is.eq r214 0u32 into r215; + cast 0field r211 r0[1u32].siblings[3u32] into r216 as [field; 3u32]; + cast 0field r0[1u32].siblings[3u32] r211 into r217 as [field; 3u32]; + ternary r215 r216[0u32] r217[0u32] into r218; + ternary r215 r216[1u32] r217[1u32] into r219; + ternary r215 r216[2u32] r217[2u32] into r220; + cast r218 r219 r220 into r221 as [field; 3u32]; + hash.psd4 r221 into r222 as field; + is.eq r0[1u32].siblings[4u32] 0field into r223; + div r0[1u32].leaf_index 8u32 into r224; + rem r224 2u32 into r225; + is.eq r225 0u32 into r226; + cast 0field r222 r0[1u32].siblings[4u32] into r227 as [field; 3u32]; + cast 0field r0[1u32].siblings[4u32] r222 into r228 as [field; 3u32]; + ternary r226 r227[0u32] r228[0u32] into r229; + ternary r226 r227[1u32] r228[1u32] into r230; + ternary r226 r227[2u32] r228[2u32] into r231; + cast r229 r230 r231 into r232 as [field; 3u32]; + hash.psd4 r232 into r233 as field; + is.eq r0[1u32].siblings[5u32] 0field into r234; + div r0[1u32].leaf_index 16u32 into r235; + rem r235 2u32 into r236; + is.eq r236 0u32 into r237; + cast 0field r233 r0[1u32].siblings[5u32] into r238 as [field; 3u32]; + cast 0field r0[1u32].siblings[5u32] r233 into r239 as [field; 3u32]; + ternary r237 r238[0u32] r239[0u32] into r240; + ternary r237 r238[1u32] r239[1u32] into r241; + ternary r237 r238[2u32] r239[2u32] into r242; + cast r240 r241 r242 into r243 as [field; 3u32]; + hash.psd4 r243 into r244 as field; + is.eq r0[1u32].siblings[6u32] 0field into r245; + div r0[1u32].leaf_index 32u32 into r246; + rem r246 2u32 into r247; + is.eq r247 0u32 into r248; + cast 0field r244 r0[1u32].siblings[6u32] into r249 as [field; 3u32]; + cast 0field r0[1u32].siblings[6u32] r244 into r250 as [field; 3u32]; + ternary r248 r249[0u32] r250[0u32] into r251; + ternary r248 r249[1u32] r250[1u32] into r252; + ternary r248 r249[2u32] r250[2u32] into r253; + cast r251 r252 r253 into r254 as [field; 3u32]; + hash.psd4 r254 into r255 as field; + is.eq r0[1u32].siblings[7u32] 0field into r256; + div r0[1u32].leaf_index 64u32 into r257; + rem r257 2u32 into r258; + is.eq r258 0u32 into r259; + cast 0field r255 r0[1u32].siblings[7u32] into r260 as [field; 3u32]; + cast 0field r0[1u32].siblings[7u32] r255 into r261 as [field; 3u32]; + ternary r259 r260[0u32] r261[0u32] into r262; + ternary r259 r260[1u32] r261[1u32] into r263; + ternary r259 r260[2u32] r261[2u32] into r264; + cast r262 r263 r264 into r265 as [field; 3u32]; + hash.psd4 r265 into r266 as field; + is.eq r0[1u32].siblings[8u32] 0field into r267; + div r0[1u32].leaf_index 128u32 into r268; + rem r268 2u32 into r269; + is.eq r269 0u32 into r270; + cast 0field r266 r0[1u32].siblings[8u32] into r271 as [field; 3u32]; + cast 0field r0[1u32].siblings[8u32] r266 into r272 as [field; 3u32]; + ternary r270 r271[0u32] r272[0u32] into r273; + ternary r270 r271[1u32] r272[1u32] into r274; + ternary r270 r271[2u32] r272[2u32] into r275; + cast r273 r274 r275 into r276 as [field; 3u32]; + hash.psd4 r276 into r277 as field; + is.eq r0[1u32].siblings[9u32] 0field into r278; + div r0[1u32].leaf_index 256u32 into r279; + rem r279 2u32 into r280; + is.eq r280 0u32 into r281; + cast 0field r277 r0[1u32].siblings[9u32] into r282 as [field; 3u32]; + cast 0field r0[1u32].siblings[9u32] r277 into r283 as [field; 3u32]; + ternary r281 r282[0u32] r283[0u32] into r284; + ternary r281 r282[1u32] r283[1u32] into r285; + ternary r281 r282[2u32] r283[2u32] into r286; + cast r284 r285 r286 into r287 as [field; 3u32]; + hash.psd4 r287 into r288 as field; + is.eq r0[1u32].siblings[10u32] 0field into r289; + div r0[1u32].leaf_index 512u32 into r290; + rem r290 2u32 into r291; + is.eq r291 0u32 into r292; + cast 0field r288 r0[1u32].siblings[10u32] into r293 as [field; 3u32]; + cast 0field r0[1u32].siblings[10u32] r288 into r294 as [field; 3u32]; + ternary r292 r293[0u32] r294[0u32] into r295; + ternary r292 r293[1u32] r294[1u32] into r296; + ternary r292 r293[2u32] r294[2u32] into r297; + cast r295 r296 r297 into r298 as [field; 3u32]; + hash.psd4 r298 into r299 as field; + is.eq r0[1u32].siblings[11u32] 0field into r300; + div r0[1u32].leaf_index 1024u32 into r301; + rem r301 2u32 into r302; + is.eq r302 0u32 into r303; + cast 0field r299 r0[1u32].siblings[11u32] into r304 as [field; 3u32]; + cast 0field r0[1u32].siblings[11u32] r299 into r305 as [field; 3u32]; + ternary r303 r304[0u32] r305[0u32] into r306; + ternary r303 r304[1u32] r305[1u32] into r307; + ternary r303 r304[2u32] r305[2u32] into r308; + cast r306 r307 r308 into r309 as [field; 3u32]; + hash.psd4 r309 into r310 as field; + is.eq r0[1u32].siblings[12u32] 0field into r311; + div r0[1u32].leaf_index 2048u32 into r312; + rem r312 2u32 into r313; + is.eq r313 0u32 into r314; + cast 0field r310 r0[1u32].siblings[12u32] into r315 as [field; 3u32]; + cast 0field r0[1u32].siblings[12u32] r310 into r316 as [field; 3u32]; + ternary r314 r315[0u32] r316[0u32] into r317; + ternary r314 r315[1u32] r316[1u32] into r318; + ternary r314 r315[2u32] r316[2u32] into r319; + cast r317 r318 r319 into r320 as [field; 3u32]; + hash.psd4 r320 into r321 as field; + is.eq r0[1u32].siblings[13u32] 0field into r322; + div r0[1u32].leaf_index 4096u32 into r323; + rem r323 2u32 into r324; + is.eq r324 0u32 into r325; + cast 0field r321 r0[1u32].siblings[13u32] into r326 as [field; 3u32]; + cast 0field r0[1u32].siblings[13u32] r321 into r327 as [field; 3u32]; + ternary r325 r326[0u32] r327[0u32] into r328; + ternary r325 r326[1u32] r327[1u32] into r329; + ternary r325 r326[2u32] r327[2u32] into r330; + cast r328 r329 r330 into r331 as [field; 3u32]; + hash.psd4 r331 into r332 as field; + is.eq r0[1u32].siblings[14u32] 0field into r333; + div r0[1u32].leaf_index 8192u32 into r334; + rem r334 2u32 into r335; + is.eq r335 0u32 into r336; + cast 0field r332 r0[1u32].siblings[14u32] into r337 as [field; 3u32]; + cast 0field r0[1u32].siblings[14u32] r332 into r338 as [field; 3u32]; + ternary r336 r337[0u32] r338[0u32] into r339; + ternary r336 r337[1u32] r338[1u32] into r340; + ternary r336 r337[2u32] r338[2u32] into r341; + cast r339 r340 r341 into r342 as [field; 3u32]; + hash.psd4 r342 into r343 as field; + is.eq r0[1u32].siblings[15u32] 0field into r344; + div r0[1u32].leaf_index 16384u32 into r345; + rem r345 2u32 into r346; + is.eq r346 0u32 into r347; + cast 0field r343 r0[1u32].siblings[15u32] into r348 as [field; 3u32]; + cast 0field r0[1u32].siblings[15u32] r343 into r349 as [field; 3u32]; + ternary r347 r348[0u32] r349[0u32] into r350; + ternary r347 r348[1u32] r349[1u32] into r351; + ternary r347 r348[2u32] r349[2u32] into r352; + cast r350 r351 r352 into r353 as [field; 3u32]; + hash.psd4 r353 into r354 as field; + ternary r344 r343 r354 into r355; + ternary r344 14u32 15u32 into r356; + ternary r333 r332 r355 into r357; + ternary r333 13u32 r356 into r358; + ternary r322 r321 r357 into r359; + ternary r322 12u32 r358 into r360; + ternary r311 r310 r359 into r361; + ternary r311 11u32 r360 into r362; + ternary r300 r299 r361 into r363; + ternary r300 10u32 r362 into r364; + ternary r289 r288 r363 into r365; + ternary r289 9u32 r364 into r366; + ternary r278 r277 r365 into r367; + ternary r278 8u32 r366 into r368; + ternary r267 r266 r367 into r369; + ternary r267 7u32 r368 into r370; + ternary r256 r255 r369 into r371; + ternary r256 6u32 r370 into r372; + ternary r245 r244 r371 into r373; + ternary r245 5u32 r372 into r374; + ternary r234 r233 r373 into r375; + ternary r234 4u32 r374 into r376; + ternary r223 r222 r375 into r377; + ternary r223 3u32 r376 into r378; + ternary r212 r211 r377 into r379; + ternary r212 2u32 r378 into r380; + ternary r201 r200 r379 into r381; + ternary r201 1u32 r380 into r382; + assert.eq r190 r381; + assert.eq r191 r382; + cast self.signer into r383 as field; + is.eq r0[0u32].leaf_index r0[1u32].leaf_index into r384; + is.eq r0[0u32].leaf_index 0u32 into r385; + lt r383 r0[0u32].siblings[0u32] into r386; + and r384 r385 into r387; + not r387 into r388; + or r386 r388 into r389; + assert.eq r389 true; + not r385 into r390; + pow 2u32 r191 into r391; + sub r391 1u32 into r392; + and r384 r390 into r393; + not r393 into r394; + is.eq r0[0u32].leaf_index r392 into r395; + or r395 r394 into r396; + assert.eq r396 true; + gt r383 r0[0u32].siblings[0u32] into r397; + or r397 r394 into r398; + assert.eq r398 true; + not r384 into r399; + gt r383 r0[0u32].siblings[0u32] into r400; + not r399 into r401; + or r400 r401 into r402; + assert.eq r402 true; + lt r383 r0[1u32].siblings[0u32] into r403; + or r403 r401 into r404; + assert.eq r404 true; + lte r0[1u32].leaf_index r392 into r405; + or r405 r401 into r406; + assert.eq r406 true; + add r0[0u32].leaf_index 1u32 into r407; + is.eq r407 r0[1u32].leaf_index into r408; + or r408 r401 into r409; + assert.eq r409 true; + cast self.signer r190 into r410 as Credentials.record; + async get_credentials r190 into r411; + output r410 as Credentials.record; + output r411 as test_usdcx_stablecoin.aleo/get_credentials.future; + +finalize get_credentials: + input r0 as field.public; + get test_usdcx_freezelist.aleo/freeze_list_root[1u8] into r1; + get test_usdcx_freezelist.aleo/block_height_window[true] into r2; + is.neq r1 r0 into r3; + branch.eq r3 false to end_then_0_2; + get test_usdcx_freezelist.aleo/freeze_list_root[2u8] into r4; + assert.eq r0 r4; + get test_usdcx_freezelist.aleo/root_updated_height[true] into r5; + add r5 r2 into r6; + gt r6 block.height into r7; + assert.eq r7 true; + branch.eq true true to end_otherwise_0_3; + position end_then_0_2; + position end_otherwise_0_3; + +function mint_public: + input r0 as address.public; + input r1 as u128.public; + async mint_public r0 r1 self.caller into r2; + output r2 as test_usdcx_stablecoin.aleo/mint_public.future; + +finalize mint_public: + input r0 as address.public; + input r1 as u128.public; + input r2 as address.public; + get address_to_role[r2] into r3; + and r3 1u16 into r4; + is.eq r4 1u16 into r5; + assert.eq r5 true; + get pause[true] into r6; + assert.eq r6 false; + get token_info[true] into r7; + add r7.supply r1 into r8; + lte r8 r7.max_supply into r9; + assert.eq r9 true; + get.or_use balances[r0] 0u128 into r10; + add r1 r10 into r11; + set r11 into balances[r0]; + cast r7.name r7.symbol r7.decimals r8 r7.max_supply into r12 as TokenInfo; + set r12 into token_info[true]; + +function mint_private: + input r0 as address.private; + input r1 as u128.public; + cast r0 r1 into r2 as Token.record; + cast aleo1mnldqsfrwayzfep3t9zusu4y7yknsdhfwx76v5pajla35mrqn5xsvvurhy r1 aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc r0 into r3 as ComplianceRecord.record; + async mint_private r1 self.caller into r4; + output r3 as ComplianceRecord.record; + output r2 as Token.record; + output r4 as test_usdcx_stablecoin.aleo/mint_private.future; + +finalize mint_private: + input r0 as u128.public; + input r1 as address.public; + get address_to_role[r1] into r2; + and r2 1u16 into r3; + is.eq r3 1u16 into r4; + assert.eq r4 true; + get pause[true] into r5; + assert.eq r5 false; + get token_info[true] into r6; + add r6.supply r0 into r7; + lte r7 r6.max_supply into r8; + assert.eq r8 true; + cast r6.name r6.symbol r6.decimals r7 r6.max_supply into r9 as TokenInfo; + set r9 into token_info[true]; + +function burn_public: + input r0 as address.public; + input r1 as u128.public; + async burn_public r0 r1 self.caller into r2; + output r2 as test_usdcx_stablecoin.aleo/burn_public.future; + +finalize burn_public: + input r0 as address.public; + input r1 as u128.public; + input r2 as address.public; + get address_to_role[r2] into r3; + and r3 2u16 into r4; + is.eq r4 2u16 into r5; + assert.eq r5 true; + get pause[true] into r6; + assert.eq r6 false; + get balances[r0] into r7; + sub r7 r1 into r8; + set r8 into balances[r0]; + get token_info[true] into r9; + sub r9.supply r1 into r10; + cast r9.name r9.symbol r9.decimals r10 r9.max_supply into r11 as TokenInfo; + set r11 into token_info[true]; + +function burn_private: + input r0 as Token.record; + input r1 as u128.public; + sub r0.amount r1 into r2; + cast r0.owner r2 into r3 as Token.record; + cast aleo1mnldqsfrwayzfep3t9zusu4y7yknsdhfwx76v5pajla35mrqn5xsvvurhy r1 r0.owner aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc into r4 as ComplianceRecord.record; + async burn_private r1 self.caller into r5; + output r4 as ComplianceRecord.record; + output r3 as Token.record; + output r5 as test_usdcx_stablecoin.aleo/burn_private.future; + +finalize burn_private: + input r0 as u128.public; + input r1 as address.public; + get address_to_role[r1] into r2; + and r2 2u16 into r3; + is.eq r3 2u16 into r4; + assert.eq r4 true; + get pause[true] into r5; + assert.eq r5 false; + get token_info[true] into r6; + sub r6.supply r0 into r7; + cast r6.name r6.symbol r6.decimals r7 r6.max_supply into r8 as TokenInfo; + set r8 into token_info[true]; + +function transfer_public: + input r0 as address.public; + input r1 as u128.public; + async transfer_public r0 r1 self.caller into r2; + output r2 as test_usdcx_stablecoin.aleo/transfer_public.future; + +finalize transfer_public: + input r0 as address.public; + input r1 as u128.public; + input r2 as address.public; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r2] false into r3; + assert.eq r3 false; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r0] false into r4; + assert.eq r4 false; + get pause[true] into r5; + assert.eq r5 false; + get balances[r2] into r6; + sub r6 r1 into r7; + set r7 into balances[r2]; + get.or_use balances[r0] 0u128 into r8; + add r8 r1 into r9; + set r9 into balances[r0]; + +function transfer_public_as_signer: + input r0 as address.public; + input r1 as u128.public; + async transfer_public_as_signer r0 r1 self.signer into r2; + output r2 as test_usdcx_stablecoin.aleo/transfer_public_as_signer.future; + +finalize transfer_public_as_signer: + input r0 as address.public; + input r1 as u128.public; + input r2 as address.public; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r2] false into r3; + assert.eq r3 false; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r0] false into r4; + assert.eq r4 false; + get pause[true] into r5; + assert.eq r5 false; + get balances[r2] into r6; + sub r6 r1 into r7; + set r7 into balances[r2]; + get.or_use balances[r0] 0u128 into r8; + add r8 r1 into r9; + set r9 into balances[r0]; + +function approve_public: + input r0 as address.public; + input r1 as u128.public; + cast self.caller r0 into r2 as TokenAllowance; + hash.bhp256 r2 into r3 as field; + async approve_public r1 r3 into r4; + output r4 as test_usdcx_stablecoin.aleo/approve_public.future; + +finalize approve_public: + input r0 as u128.public; + input r1 as field.public; + get pause[true] into r2; + assert.eq r2 false; + get.or_use allowances[r1] 0u128 into r3; + add r3 r0 into r4; + set r4 into allowances[r1]; + +function unapprove_public: + input r0 as address.public; + input r1 as u128.public; + cast self.caller r0 into r2 as TokenAllowance; + hash.bhp256 r2 into r3 as field; + async unapprove_public r1 r3 into r4; + output r4 as test_usdcx_stablecoin.aleo/unapprove_public.future; + +finalize unapprove_public: + input r0 as u128.public; + input r1 as field.public; + get pause[true] into r2; + assert.eq r2 false; + get allowances[r1] into r3; + sub r3 r0 into r4; + set r4 into allowances[r1]; + +function transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + cast r0 self.caller into r3 as TokenAllowance; + hash.bhp256 r3 into r4 as field; + async transfer_from_public r0 r1 r2 r4 into r5; + output r5 as test_usdcx_stablecoin.aleo/transfer_from_public.future; + +finalize transfer_from_public: + input r0 as address.public; + input r1 as address.public; + input r2 as u128.public; + input r3 as field.public; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r0] false into r4; + assert.eq r4 false; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r1] false into r5; + assert.eq r5 false; + get pause[true] into r6; + assert.eq r6 false; + get allowances[r3] into r7; + sub r7 r2 into r8; + set r8 into allowances[r3]; + get balances[r0] into r9; + sub r9 r2 into r10; + set r10 into balances[r0]; + get.or_use balances[r1] 0u128 into r11; + add r11 r2 into r12; + set r12 into balances[r1]; + +function transfer_public_to_private: + input r0 as address.private; + input r1 as u128.public; + cast r0 r1 into r2 as Token.record; + cast aleo1mnldqsfrwayzfep3t9zusu4y7yknsdhfwx76v5pajla35mrqn5xsvvurhy r1 self.caller r0 into r3 as ComplianceRecord.record; + async transfer_public_to_private r1 self.caller into r4; + output r3 as ComplianceRecord.record; + output r2 as Token.record; + output r4 as test_usdcx_stablecoin.aleo/transfer_public_to_private.future; + +finalize transfer_public_to_private: + input r0 as u128.public; + input r1 as address.public; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r1] false into r2; + assert.eq r2 false; + get pause[true] into r3; + assert.eq r3 false; + get balances[r1] into r4; + sub r4 r0 into r5; + set r5 into balances[r1]; + +function transfer_from_public_to_private: + input r0 as address.public; + input r1 as address.private; + input r2 as u128.public; + cast r1 r2 into r3 as Token.record; + cast r0 self.caller into r4 as TokenAllowance; + hash.bhp256 r4 into r5 as field; + cast aleo1mnldqsfrwayzfep3t9zusu4y7yknsdhfwx76v5pajla35mrqn5xsvvurhy r2 r0 r1 into r6 as ComplianceRecord.record; + async transfer_from_public_to_private r0 r2 r5 into r7; + output r6 as ComplianceRecord.record; + output r3 as Token.record; + output r7 as test_usdcx_stablecoin.aleo/transfer_from_public_to_private.future; + +finalize transfer_from_public_to_private: + input r0 as address.public; + input r1 as u128.public; + input r2 as field.public; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r0] false into r3; + assert.eq r3 false; + get pause[true] into r4; + assert.eq r4 false; + get allowances[r2] into r5; + sub r5 r1 into r6; + set r6 into allowances[r2]; + get balances[r0] into r7; + sub r7 r1 into r8; + set r8 into balances[r0]; + +function transfer_private: + input r0 as address.private; + input r1 as u128.private; + input r2 as Token.record; + input r3 as [MerkleProof; 2u32].private; + rem r3[0u32].leaf_index 2u32 into r4; + is.eq r4 0u32 into r5; + cast 1field r3[0u32].siblings[0u32] r3[0u32].siblings[1u32] into r6 as [field; 3u32]; + cast 1field r3[0u32].siblings[1u32] r3[0u32].siblings[0u32] into r7 as [field; 3u32]; + ternary r5 r6[0u32] r7[0u32] into r8; + ternary r5 r6[1u32] r7[1u32] into r9; + ternary r5 r6[2u32] r7[2u32] into r10; + cast r8 r9 r10 into r11 as [field; 3u32]; + hash.psd4 r11 into r12 as field; + is.eq r3[0u32].siblings[2u32] 0field into r13; + div r3[0u32].leaf_index 2u32 into r14; + rem r14 2u32 into r15; + is.eq r15 0u32 into r16; + cast 0field r12 r3[0u32].siblings[2u32] into r17 as [field; 3u32]; + cast 0field r3[0u32].siblings[2u32] r12 into r18 as [field; 3u32]; + ternary r16 r17[0u32] r18[0u32] into r19; + ternary r16 r17[1u32] r18[1u32] into r20; + ternary r16 r17[2u32] r18[2u32] into r21; + cast r19 r20 r21 into r22 as [field; 3u32]; + hash.psd4 r22 into r23 as field; + is.eq r3[0u32].siblings[3u32] 0field into r24; + div r3[0u32].leaf_index 4u32 into r25; + rem r25 2u32 into r26; + is.eq r26 0u32 into r27; + cast 0field r23 r3[0u32].siblings[3u32] into r28 as [field; 3u32]; + cast 0field r3[0u32].siblings[3u32] r23 into r29 as [field; 3u32]; + ternary r27 r28[0u32] r29[0u32] into r30; + ternary r27 r28[1u32] r29[1u32] into r31; + ternary r27 r28[2u32] r29[2u32] into r32; + cast r30 r31 r32 into r33 as [field; 3u32]; + hash.psd4 r33 into r34 as field; + is.eq r3[0u32].siblings[4u32] 0field into r35; + div r3[0u32].leaf_index 8u32 into r36; + rem r36 2u32 into r37; + is.eq r37 0u32 into r38; + cast 0field r34 r3[0u32].siblings[4u32] into r39 as [field; 3u32]; + cast 0field r3[0u32].siblings[4u32] r34 into r40 as [field; 3u32]; + ternary r38 r39[0u32] r40[0u32] into r41; + ternary r38 r39[1u32] r40[1u32] into r42; + ternary r38 r39[2u32] r40[2u32] into r43; + cast r41 r42 r43 into r44 as [field; 3u32]; + hash.psd4 r44 into r45 as field; + is.eq r3[0u32].siblings[5u32] 0field into r46; + div r3[0u32].leaf_index 16u32 into r47; + rem r47 2u32 into r48; + is.eq r48 0u32 into r49; + cast 0field r45 r3[0u32].siblings[5u32] into r50 as [field; 3u32]; + cast 0field r3[0u32].siblings[5u32] r45 into r51 as [field; 3u32]; + ternary r49 r50[0u32] r51[0u32] into r52; + ternary r49 r50[1u32] r51[1u32] into r53; + ternary r49 r50[2u32] r51[2u32] into r54; + cast r52 r53 r54 into r55 as [field; 3u32]; + hash.psd4 r55 into r56 as field; + is.eq r3[0u32].siblings[6u32] 0field into r57; + div r3[0u32].leaf_index 32u32 into r58; + rem r58 2u32 into r59; + is.eq r59 0u32 into r60; + cast 0field r56 r3[0u32].siblings[6u32] into r61 as [field; 3u32]; + cast 0field r3[0u32].siblings[6u32] r56 into r62 as [field; 3u32]; + ternary r60 r61[0u32] r62[0u32] into r63; + ternary r60 r61[1u32] r62[1u32] into r64; + ternary r60 r61[2u32] r62[2u32] into r65; + cast r63 r64 r65 into r66 as [field; 3u32]; + hash.psd4 r66 into r67 as field; + is.eq r3[0u32].siblings[7u32] 0field into r68; + div r3[0u32].leaf_index 64u32 into r69; + rem r69 2u32 into r70; + is.eq r70 0u32 into r71; + cast 0field r67 r3[0u32].siblings[7u32] into r72 as [field; 3u32]; + cast 0field r3[0u32].siblings[7u32] r67 into r73 as [field; 3u32]; + ternary r71 r72[0u32] r73[0u32] into r74; + ternary r71 r72[1u32] r73[1u32] into r75; + ternary r71 r72[2u32] r73[2u32] into r76; + cast r74 r75 r76 into r77 as [field; 3u32]; + hash.psd4 r77 into r78 as field; + is.eq r3[0u32].siblings[8u32] 0field into r79; + div r3[0u32].leaf_index 128u32 into r80; + rem r80 2u32 into r81; + is.eq r81 0u32 into r82; + cast 0field r78 r3[0u32].siblings[8u32] into r83 as [field; 3u32]; + cast 0field r3[0u32].siblings[8u32] r78 into r84 as [field; 3u32]; + ternary r82 r83[0u32] r84[0u32] into r85; + ternary r82 r83[1u32] r84[1u32] into r86; + ternary r82 r83[2u32] r84[2u32] into r87; + cast r85 r86 r87 into r88 as [field; 3u32]; + hash.psd4 r88 into r89 as field; + is.eq r3[0u32].siblings[9u32] 0field into r90; + div r3[0u32].leaf_index 256u32 into r91; + rem r91 2u32 into r92; + is.eq r92 0u32 into r93; + cast 0field r89 r3[0u32].siblings[9u32] into r94 as [field; 3u32]; + cast 0field r3[0u32].siblings[9u32] r89 into r95 as [field; 3u32]; + ternary r93 r94[0u32] r95[0u32] into r96; + ternary r93 r94[1u32] r95[1u32] into r97; + ternary r93 r94[2u32] r95[2u32] into r98; + cast r96 r97 r98 into r99 as [field; 3u32]; + hash.psd4 r99 into r100 as field; + is.eq r3[0u32].siblings[10u32] 0field into r101; + div r3[0u32].leaf_index 512u32 into r102; + rem r102 2u32 into r103; + is.eq r103 0u32 into r104; + cast 0field r100 r3[0u32].siblings[10u32] into r105 as [field; 3u32]; + cast 0field r3[0u32].siblings[10u32] r100 into r106 as [field; 3u32]; + ternary r104 r105[0u32] r106[0u32] into r107; + ternary r104 r105[1u32] r106[1u32] into r108; + ternary r104 r105[2u32] r106[2u32] into r109; + cast r107 r108 r109 into r110 as [field; 3u32]; + hash.psd4 r110 into r111 as field; + is.eq r3[0u32].siblings[11u32] 0field into r112; + div r3[0u32].leaf_index 1024u32 into r113; + rem r113 2u32 into r114; + is.eq r114 0u32 into r115; + cast 0field r111 r3[0u32].siblings[11u32] into r116 as [field; 3u32]; + cast 0field r3[0u32].siblings[11u32] r111 into r117 as [field; 3u32]; + ternary r115 r116[0u32] r117[0u32] into r118; + ternary r115 r116[1u32] r117[1u32] into r119; + ternary r115 r116[2u32] r117[2u32] into r120; + cast r118 r119 r120 into r121 as [field; 3u32]; + hash.psd4 r121 into r122 as field; + is.eq r3[0u32].siblings[12u32] 0field into r123; + div r3[0u32].leaf_index 2048u32 into r124; + rem r124 2u32 into r125; + is.eq r125 0u32 into r126; + cast 0field r122 r3[0u32].siblings[12u32] into r127 as [field; 3u32]; + cast 0field r3[0u32].siblings[12u32] r122 into r128 as [field; 3u32]; + ternary r126 r127[0u32] r128[0u32] into r129; + ternary r126 r127[1u32] r128[1u32] into r130; + ternary r126 r127[2u32] r128[2u32] into r131; + cast r129 r130 r131 into r132 as [field; 3u32]; + hash.psd4 r132 into r133 as field; + is.eq r3[0u32].siblings[13u32] 0field into r134; + div r3[0u32].leaf_index 4096u32 into r135; + rem r135 2u32 into r136; + is.eq r136 0u32 into r137; + cast 0field r133 r3[0u32].siblings[13u32] into r138 as [field; 3u32]; + cast 0field r3[0u32].siblings[13u32] r133 into r139 as [field; 3u32]; + ternary r137 r138[0u32] r139[0u32] into r140; + ternary r137 r138[1u32] r139[1u32] into r141; + ternary r137 r138[2u32] r139[2u32] into r142; + cast r140 r141 r142 into r143 as [field; 3u32]; + hash.psd4 r143 into r144 as field; + is.eq r3[0u32].siblings[14u32] 0field into r145; + div r3[0u32].leaf_index 8192u32 into r146; + rem r146 2u32 into r147; + is.eq r147 0u32 into r148; + cast 0field r144 r3[0u32].siblings[14u32] into r149 as [field; 3u32]; + cast 0field r3[0u32].siblings[14u32] r144 into r150 as [field; 3u32]; + ternary r148 r149[0u32] r150[0u32] into r151; + ternary r148 r149[1u32] r150[1u32] into r152; + ternary r148 r149[2u32] r150[2u32] into r153; + cast r151 r152 r153 into r154 as [field; 3u32]; + hash.psd4 r154 into r155 as field; + is.eq r3[0u32].siblings[15u32] 0field into r156; + div r3[0u32].leaf_index 16384u32 into r157; + rem r157 2u32 into r158; + is.eq r158 0u32 into r159; + cast 0field r155 r3[0u32].siblings[15u32] into r160 as [field; 3u32]; + cast 0field r3[0u32].siblings[15u32] r155 into r161 as [field; 3u32]; + ternary r159 r160[0u32] r161[0u32] into r162; + ternary r159 r160[1u32] r161[1u32] into r163; + ternary r159 r160[2u32] r161[2u32] into r164; + cast r162 r163 r164 into r165 as [field; 3u32]; + hash.psd4 r165 into r166 as field; + ternary r156 r155 r166 into r167; + ternary r156 14u32 15u32 into r168; + ternary r145 r144 r167 into r169; + ternary r145 13u32 r168 into r170; + ternary r134 r133 r169 into r171; + ternary r134 12u32 r170 into r172; + ternary r123 r122 r171 into r173; + ternary r123 11u32 r172 into r174; + ternary r112 r111 r173 into r175; + ternary r112 10u32 r174 into r176; + ternary r101 r100 r175 into r177; + ternary r101 9u32 r176 into r178; + ternary r90 r89 r177 into r179; + ternary r90 8u32 r178 into r180; + ternary r79 r78 r179 into r181; + ternary r79 7u32 r180 into r182; + ternary r68 r67 r181 into r183; + ternary r68 6u32 r182 into r184; + ternary r57 r56 r183 into r185; + ternary r57 5u32 r184 into r186; + ternary r46 r45 r185 into r187; + ternary r46 4u32 r186 into r188; + ternary r35 r34 r187 into r189; + ternary r35 3u32 r188 into r190; + ternary r24 r23 r189 into r191; + ternary r24 2u32 r190 into r192; + ternary r13 r12 r191 into r193; + ternary r13 1u32 r192 into r194; + rem r3[1u32].leaf_index 2u32 into r195; + is.eq r195 0u32 into r196; + cast 1field r3[1u32].siblings[0u32] r3[1u32].siblings[1u32] into r197 as [field; 3u32]; + cast 1field r3[1u32].siblings[1u32] r3[1u32].siblings[0u32] into r198 as [field; 3u32]; + ternary r196 r197[0u32] r198[0u32] into r199; + ternary r196 r197[1u32] r198[1u32] into r200; + ternary r196 r197[2u32] r198[2u32] into r201; + cast r199 r200 r201 into r202 as [field; 3u32]; + hash.psd4 r202 into r203 as field; + is.eq r3[1u32].siblings[2u32] 0field into r204; + div r3[1u32].leaf_index 2u32 into r205; + rem r205 2u32 into r206; + is.eq r206 0u32 into r207; + cast 0field r203 r3[1u32].siblings[2u32] into r208 as [field; 3u32]; + cast 0field r3[1u32].siblings[2u32] r203 into r209 as [field; 3u32]; + ternary r207 r208[0u32] r209[0u32] into r210; + ternary r207 r208[1u32] r209[1u32] into r211; + ternary r207 r208[2u32] r209[2u32] into r212; + cast r210 r211 r212 into r213 as [field; 3u32]; + hash.psd4 r213 into r214 as field; + is.eq r3[1u32].siblings[3u32] 0field into r215; + div r3[1u32].leaf_index 4u32 into r216; + rem r216 2u32 into r217; + is.eq r217 0u32 into r218; + cast 0field r214 r3[1u32].siblings[3u32] into r219 as [field; 3u32]; + cast 0field r3[1u32].siblings[3u32] r214 into r220 as [field; 3u32]; + ternary r218 r219[0u32] r220[0u32] into r221; + ternary r218 r219[1u32] r220[1u32] into r222; + ternary r218 r219[2u32] r220[2u32] into r223; + cast r221 r222 r223 into r224 as [field; 3u32]; + hash.psd4 r224 into r225 as field; + is.eq r3[1u32].siblings[4u32] 0field into r226; + div r3[1u32].leaf_index 8u32 into r227; + rem r227 2u32 into r228; + is.eq r228 0u32 into r229; + cast 0field r225 r3[1u32].siblings[4u32] into r230 as [field; 3u32]; + cast 0field r3[1u32].siblings[4u32] r225 into r231 as [field; 3u32]; + ternary r229 r230[0u32] r231[0u32] into r232; + ternary r229 r230[1u32] r231[1u32] into r233; + ternary r229 r230[2u32] r231[2u32] into r234; + cast r232 r233 r234 into r235 as [field; 3u32]; + hash.psd4 r235 into r236 as field; + is.eq r3[1u32].siblings[5u32] 0field into r237; + div r3[1u32].leaf_index 16u32 into r238; + rem r238 2u32 into r239; + is.eq r239 0u32 into r240; + cast 0field r236 r3[1u32].siblings[5u32] into r241 as [field; 3u32]; + cast 0field r3[1u32].siblings[5u32] r236 into r242 as [field; 3u32]; + ternary r240 r241[0u32] r242[0u32] into r243; + ternary r240 r241[1u32] r242[1u32] into r244; + ternary r240 r241[2u32] r242[2u32] into r245; + cast r243 r244 r245 into r246 as [field; 3u32]; + hash.psd4 r246 into r247 as field; + is.eq r3[1u32].siblings[6u32] 0field into r248; + div r3[1u32].leaf_index 32u32 into r249; + rem r249 2u32 into r250; + is.eq r250 0u32 into r251; + cast 0field r247 r3[1u32].siblings[6u32] into r252 as [field; 3u32]; + cast 0field r3[1u32].siblings[6u32] r247 into r253 as [field; 3u32]; + ternary r251 r252[0u32] r253[0u32] into r254; + ternary r251 r252[1u32] r253[1u32] into r255; + ternary r251 r252[2u32] r253[2u32] into r256; + cast r254 r255 r256 into r257 as [field; 3u32]; + hash.psd4 r257 into r258 as field; + is.eq r3[1u32].siblings[7u32] 0field into r259; + div r3[1u32].leaf_index 64u32 into r260; + rem r260 2u32 into r261; + is.eq r261 0u32 into r262; + cast 0field r258 r3[1u32].siblings[7u32] into r263 as [field; 3u32]; + cast 0field r3[1u32].siblings[7u32] r258 into r264 as [field; 3u32]; + ternary r262 r263[0u32] r264[0u32] into r265; + ternary r262 r263[1u32] r264[1u32] into r266; + ternary r262 r263[2u32] r264[2u32] into r267; + cast r265 r266 r267 into r268 as [field; 3u32]; + hash.psd4 r268 into r269 as field; + is.eq r3[1u32].siblings[8u32] 0field into r270; + div r3[1u32].leaf_index 128u32 into r271; + rem r271 2u32 into r272; + is.eq r272 0u32 into r273; + cast 0field r269 r3[1u32].siblings[8u32] into r274 as [field; 3u32]; + cast 0field r3[1u32].siblings[8u32] r269 into r275 as [field; 3u32]; + ternary r273 r274[0u32] r275[0u32] into r276; + ternary r273 r274[1u32] r275[1u32] into r277; + ternary r273 r274[2u32] r275[2u32] into r278; + cast r276 r277 r278 into r279 as [field; 3u32]; + hash.psd4 r279 into r280 as field; + is.eq r3[1u32].siblings[9u32] 0field into r281; + div r3[1u32].leaf_index 256u32 into r282; + rem r282 2u32 into r283; + is.eq r283 0u32 into r284; + cast 0field r280 r3[1u32].siblings[9u32] into r285 as [field; 3u32]; + cast 0field r3[1u32].siblings[9u32] r280 into r286 as [field; 3u32]; + ternary r284 r285[0u32] r286[0u32] into r287; + ternary r284 r285[1u32] r286[1u32] into r288; + ternary r284 r285[2u32] r286[2u32] into r289; + cast r287 r288 r289 into r290 as [field; 3u32]; + hash.psd4 r290 into r291 as field; + is.eq r3[1u32].siblings[10u32] 0field into r292; + div r3[1u32].leaf_index 512u32 into r293; + rem r293 2u32 into r294; + is.eq r294 0u32 into r295; + cast 0field r291 r3[1u32].siblings[10u32] into r296 as [field; 3u32]; + cast 0field r3[1u32].siblings[10u32] r291 into r297 as [field; 3u32]; + ternary r295 r296[0u32] r297[0u32] into r298; + ternary r295 r296[1u32] r297[1u32] into r299; + ternary r295 r296[2u32] r297[2u32] into r300; + cast r298 r299 r300 into r301 as [field; 3u32]; + hash.psd4 r301 into r302 as field; + is.eq r3[1u32].siblings[11u32] 0field into r303; + div r3[1u32].leaf_index 1024u32 into r304; + rem r304 2u32 into r305; + is.eq r305 0u32 into r306; + cast 0field r302 r3[1u32].siblings[11u32] into r307 as [field; 3u32]; + cast 0field r3[1u32].siblings[11u32] r302 into r308 as [field; 3u32]; + ternary r306 r307[0u32] r308[0u32] into r309; + ternary r306 r307[1u32] r308[1u32] into r310; + ternary r306 r307[2u32] r308[2u32] into r311; + cast r309 r310 r311 into r312 as [field; 3u32]; + hash.psd4 r312 into r313 as field; + is.eq r3[1u32].siblings[12u32] 0field into r314; + div r3[1u32].leaf_index 2048u32 into r315; + rem r315 2u32 into r316; + is.eq r316 0u32 into r317; + cast 0field r313 r3[1u32].siblings[12u32] into r318 as [field; 3u32]; + cast 0field r3[1u32].siblings[12u32] r313 into r319 as [field; 3u32]; + ternary r317 r318[0u32] r319[0u32] into r320; + ternary r317 r318[1u32] r319[1u32] into r321; + ternary r317 r318[2u32] r319[2u32] into r322; + cast r320 r321 r322 into r323 as [field; 3u32]; + hash.psd4 r323 into r324 as field; + is.eq r3[1u32].siblings[13u32] 0field into r325; + div r3[1u32].leaf_index 4096u32 into r326; + rem r326 2u32 into r327; + is.eq r327 0u32 into r328; + cast 0field r324 r3[1u32].siblings[13u32] into r329 as [field; 3u32]; + cast 0field r3[1u32].siblings[13u32] r324 into r330 as [field; 3u32]; + ternary r328 r329[0u32] r330[0u32] into r331; + ternary r328 r329[1u32] r330[1u32] into r332; + ternary r328 r329[2u32] r330[2u32] into r333; + cast r331 r332 r333 into r334 as [field; 3u32]; + hash.psd4 r334 into r335 as field; + is.eq r3[1u32].siblings[14u32] 0field into r336; + div r3[1u32].leaf_index 8192u32 into r337; + rem r337 2u32 into r338; + is.eq r338 0u32 into r339; + cast 0field r335 r3[1u32].siblings[14u32] into r340 as [field; 3u32]; + cast 0field r3[1u32].siblings[14u32] r335 into r341 as [field; 3u32]; + ternary r339 r340[0u32] r341[0u32] into r342; + ternary r339 r340[1u32] r341[1u32] into r343; + ternary r339 r340[2u32] r341[2u32] into r344; + cast r342 r343 r344 into r345 as [field; 3u32]; + hash.psd4 r345 into r346 as field; + is.eq r3[1u32].siblings[15u32] 0field into r347; + div r3[1u32].leaf_index 16384u32 into r348; + rem r348 2u32 into r349; + is.eq r349 0u32 into r350; + cast 0field r346 r3[1u32].siblings[15u32] into r351 as [field; 3u32]; + cast 0field r3[1u32].siblings[15u32] r346 into r352 as [field; 3u32]; + ternary r350 r351[0u32] r352[0u32] into r353; + ternary r350 r351[1u32] r352[1u32] into r354; + ternary r350 r351[2u32] r352[2u32] into r355; + cast r353 r354 r355 into r356 as [field; 3u32]; + hash.psd4 r356 into r357 as field; + ternary r347 r346 r357 into r358; + ternary r347 14u32 15u32 into r359; + ternary r336 r335 r358 into r360; + ternary r336 13u32 r359 into r361; + ternary r325 r324 r360 into r362; + ternary r325 12u32 r361 into r363; + ternary r314 r313 r362 into r364; + ternary r314 11u32 r363 into r365; + ternary r303 r302 r364 into r366; + ternary r303 10u32 r365 into r367; + ternary r292 r291 r366 into r368; + ternary r292 9u32 r367 into r369; + ternary r281 r280 r368 into r370; + ternary r281 8u32 r369 into r371; + ternary r270 r269 r370 into r372; + ternary r270 7u32 r371 into r373; + ternary r259 r258 r372 into r374; + ternary r259 6u32 r373 into r375; + ternary r248 r247 r374 into r376; + ternary r248 5u32 r375 into r377; + ternary r237 r236 r376 into r378; + ternary r237 4u32 r377 into r379; + ternary r226 r225 r378 into r380; + ternary r226 3u32 r379 into r381; + ternary r215 r214 r380 into r382; + ternary r215 2u32 r381 into r383; + ternary r204 r203 r382 into r384; + ternary r204 1u32 r383 into r385; + assert.eq r193 r384; + assert.eq r194 r385; + cast r2.owner into r386 as field; + is.eq r3[0u32].leaf_index r3[1u32].leaf_index into r387; + is.eq r3[0u32].leaf_index 0u32 into r388; + lt r386 r3[0u32].siblings[0u32] into r389; + and r387 r388 into r390; + not r390 into r391; + or r389 r391 into r392; + assert.eq r392 true; + not r388 into r393; + pow 2u32 r194 into r394; + sub r394 1u32 into r395; + and r387 r393 into r396; + not r396 into r397; + is.eq r3[0u32].leaf_index r395 into r398; + or r398 r397 into r399; + assert.eq r399 true; + gt r386 r3[0u32].siblings[0u32] into r400; + or r400 r397 into r401; + assert.eq r401 true; + not r387 into r402; + gt r386 r3[0u32].siblings[0u32] into r403; + not r402 into r404; + or r403 r404 into r405; + assert.eq r405 true; + lt r386 r3[1u32].siblings[0u32] into r406; + or r406 r404 into r407; + assert.eq r407 true; + lte r3[1u32].leaf_index r395 into r408; + or r408 r404 into r409; + assert.eq r409 true; + add r3[0u32].leaf_index 1u32 into r410; + is.eq r410 r3[1u32].leaf_index into r411; + or r411 r404 into r412; + assert.eq r412 true; + sub r2.amount r1 into r413; + cast r2.owner r413 into r414 as Token.record; + cast r0 r1 into r415 as Token.record; + cast aleo1mnldqsfrwayzfep3t9zusu4y7yknsdhfwx76v5pajla35mrqn5xsvvurhy r1 r2.owner r0 into r416 as ComplianceRecord.record; + async transfer_private r193 into r417; + output r416 as ComplianceRecord.record; + output r414 as Token.record; + output r415 as Token.record; + output r417 as test_usdcx_stablecoin.aleo/transfer_private.future; + +finalize transfer_private: + input r0 as field.public; + get pause[true] into r1; + assert.eq r1 false; + get test_usdcx_freezelist.aleo/freeze_list_root[1u8] into r2; + get test_usdcx_freezelist.aleo/block_height_window[true] into r3; + is.neq r2 r0 into r4; + branch.eq r4 false to end_then_0_4; + get test_usdcx_freezelist.aleo/freeze_list_root[2u8] into r5; + assert.eq r0 r5; + get test_usdcx_freezelist.aleo/root_updated_height[true] into r6; + add r6 r3 into r7; + gt r7 block.height into r8; + assert.eq r8 true; + branch.eq true true to end_otherwise_0_5; + position end_then_0_4; + position end_otherwise_0_5; + +function transfer_private_to_public: + input r0 as address.public; + input r1 as u128.public; + input r2 as Token.record; + input r3 as [MerkleProof; 2u32].private; + rem r3[0u32].leaf_index 2u32 into r4; + is.eq r4 0u32 into r5; + cast 1field r3[0u32].siblings[0u32] r3[0u32].siblings[1u32] into r6 as [field; 3u32]; + cast 1field r3[0u32].siblings[1u32] r3[0u32].siblings[0u32] into r7 as [field; 3u32]; + ternary r5 r6[0u32] r7[0u32] into r8; + ternary r5 r6[1u32] r7[1u32] into r9; + ternary r5 r6[2u32] r7[2u32] into r10; + cast r8 r9 r10 into r11 as [field; 3u32]; + hash.psd4 r11 into r12 as field; + is.eq r3[0u32].siblings[2u32] 0field into r13; + div r3[0u32].leaf_index 2u32 into r14; + rem r14 2u32 into r15; + is.eq r15 0u32 into r16; + cast 0field r12 r3[0u32].siblings[2u32] into r17 as [field; 3u32]; + cast 0field r3[0u32].siblings[2u32] r12 into r18 as [field; 3u32]; + ternary r16 r17[0u32] r18[0u32] into r19; + ternary r16 r17[1u32] r18[1u32] into r20; + ternary r16 r17[2u32] r18[2u32] into r21; + cast r19 r20 r21 into r22 as [field; 3u32]; + hash.psd4 r22 into r23 as field; + is.eq r3[0u32].siblings[3u32] 0field into r24; + div r3[0u32].leaf_index 4u32 into r25; + rem r25 2u32 into r26; + is.eq r26 0u32 into r27; + cast 0field r23 r3[0u32].siblings[3u32] into r28 as [field; 3u32]; + cast 0field r3[0u32].siblings[3u32] r23 into r29 as [field; 3u32]; + ternary r27 r28[0u32] r29[0u32] into r30; + ternary r27 r28[1u32] r29[1u32] into r31; + ternary r27 r28[2u32] r29[2u32] into r32; + cast r30 r31 r32 into r33 as [field; 3u32]; + hash.psd4 r33 into r34 as field; + is.eq r3[0u32].siblings[4u32] 0field into r35; + div r3[0u32].leaf_index 8u32 into r36; + rem r36 2u32 into r37; + is.eq r37 0u32 into r38; + cast 0field r34 r3[0u32].siblings[4u32] into r39 as [field; 3u32]; + cast 0field r3[0u32].siblings[4u32] r34 into r40 as [field; 3u32]; + ternary r38 r39[0u32] r40[0u32] into r41; + ternary r38 r39[1u32] r40[1u32] into r42; + ternary r38 r39[2u32] r40[2u32] into r43; + cast r41 r42 r43 into r44 as [field; 3u32]; + hash.psd4 r44 into r45 as field; + is.eq r3[0u32].siblings[5u32] 0field into r46; + div r3[0u32].leaf_index 16u32 into r47; + rem r47 2u32 into r48; + is.eq r48 0u32 into r49; + cast 0field r45 r3[0u32].siblings[5u32] into r50 as [field; 3u32]; + cast 0field r3[0u32].siblings[5u32] r45 into r51 as [field; 3u32]; + ternary r49 r50[0u32] r51[0u32] into r52; + ternary r49 r50[1u32] r51[1u32] into r53; + ternary r49 r50[2u32] r51[2u32] into r54; + cast r52 r53 r54 into r55 as [field; 3u32]; + hash.psd4 r55 into r56 as field; + is.eq r3[0u32].siblings[6u32] 0field into r57; + div r3[0u32].leaf_index 32u32 into r58; + rem r58 2u32 into r59; + is.eq r59 0u32 into r60; + cast 0field r56 r3[0u32].siblings[6u32] into r61 as [field; 3u32]; + cast 0field r3[0u32].siblings[6u32] r56 into r62 as [field; 3u32]; + ternary r60 r61[0u32] r62[0u32] into r63; + ternary r60 r61[1u32] r62[1u32] into r64; + ternary r60 r61[2u32] r62[2u32] into r65; + cast r63 r64 r65 into r66 as [field; 3u32]; + hash.psd4 r66 into r67 as field; + is.eq r3[0u32].siblings[7u32] 0field into r68; + div r3[0u32].leaf_index 64u32 into r69; + rem r69 2u32 into r70; + is.eq r70 0u32 into r71; + cast 0field r67 r3[0u32].siblings[7u32] into r72 as [field; 3u32]; + cast 0field r3[0u32].siblings[7u32] r67 into r73 as [field; 3u32]; + ternary r71 r72[0u32] r73[0u32] into r74; + ternary r71 r72[1u32] r73[1u32] into r75; + ternary r71 r72[2u32] r73[2u32] into r76; + cast r74 r75 r76 into r77 as [field; 3u32]; + hash.psd4 r77 into r78 as field; + is.eq r3[0u32].siblings[8u32] 0field into r79; + div r3[0u32].leaf_index 128u32 into r80; + rem r80 2u32 into r81; + is.eq r81 0u32 into r82; + cast 0field r78 r3[0u32].siblings[8u32] into r83 as [field; 3u32]; + cast 0field r3[0u32].siblings[8u32] r78 into r84 as [field; 3u32]; + ternary r82 r83[0u32] r84[0u32] into r85; + ternary r82 r83[1u32] r84[1u32] into r86; + ternary r82 r83[2u32] r84[2u32] into r87; + cast r85 r86 r87 into r88 as [field; 3u32]; + hash.psd4 r88 into r89 as field; + is.eq r3[0u32].siblings[9u32] 0field into r90; + div r3[0u32].leaf_index 256u32 into r91; + rem r91 2u32 into r92; + is.eq r92 0u32 into r93; + cast 0field r89 r3[0u32].siblings[9u32] into r94 as [field; 3u32]; + cast 0field r3[0u32].siblings[9u32] r89 into r95 as [field; 3u32]; + ternary r93 r94[0u32] r95[0u32] into r96; + ternary r93 r94[1u32] r95[1u32] into r97; + ternary r93 r94[2u32] r95[2u32] into r98; + cast r96 r97 r98 into r99 as [field; 3u32]; + hash.psd4 r99 into r100 as field; + is.eq r3[0u32].siblings[10u32] 0field into r101; + div r3[0u32].leaf_index 512u32 into r102; + rem r102 2u32 into r103; + is.eq r103 0u32 into r104; + cast 0field r100 r3[0u32].siblings[10u32] into r105 as [field; 3u32]; + cast 0field r3[0u32].siblings[10u32] r100 into r106 as [field; 3u32]; + ternary r104 r105[0u32] r106[0u32] into r107; + ternary r104 r105[1u32] r106[1u32] into r108; + ternary r104 r105[2u32] r106[2u32] into r109; + cast r107 r108 r109 into r110 as [field; 3u32]; + hash.psd4 r110 into r111 as field; + is.eq r3[0u32].siblings[11u32] 0field into r112; + div r3[0u32].leaf_index 1024u32 into r113; + rem r113 2u32 into r114; + is.eq r114 0u32 into r115; + cast 0field r111 r3[0u32].siblings[11u32] into r116 as [field; 3u32]; + cast 0field r3[0u32].siblings[11u32] r111 into r117 as [field; 3u32]; + ternary r115 r116[0u32] r117[0u32] into r118; + ternary r115 r116[1u32] r117[1u32] into r119; + ternary r115 r116[2u32] r117[2u32] into r120; + cast r118 r119 r120 into r121 as [field; 3u32]; + hash.psd4 r121 into r122 as field; + is.eq r3[0u32].siblings[12u32] 0field into r123; + div r3[0u32].leaf_index 2048u32 into r124; + rem r124 2u32 into r125; + is.eq r125 0u32 into r126; + cast 0field r122 r3[0u32].siblings[12u32] into r127 as [field; 3u32]; + cast 0field r3[0u32].siblings[12u32] r122 into r128 as [field; 3u32]; + ternary r126 r127[0u32] r128[0u32] into r129; + ternary r126 r127[1u32] r128[1u32] into r130; + ternary r126 r127[2u32] r128[2u32] into r131; + cast r129 r130 r131 into r132 as [field; 3u32]; + hash.psd4 r132 into r133 as field; + is.eq r3[0u32].siblings[13u32] 0field into r134; + div r3[0u32].leaf_index 4096u32 into r135; + rem r135 2u32 into r136; + is.eq r136 0u32 into r137; + cast 0field r133 r3[0u32].siblings[13u32] into r138 as [field; 3u32]; + cast 0field r3[0u32].siblings[13u32] r133 into r139 as [field; 3u32]; + ternary r137 r138[0u32] r139[0u32] into r140; + ternary r137 r138[1u32] r139[1u32] into r141; + ternary r137 r138[2u32] r139[2u32] into r142; + cast r140 r141 r142 into r143 as [field; 3u32]; + hash.psd4 r143 into r144 as field; + is.eq r3[0u32].siblings[14u32] 0field into r145; + div r3[0u32].leaf_index 8192u32 into r146; + rem r146 2u32 into r147; + is.eq r147 0u32 into r148; + cast 0field r144 r3[0u32].siblings[14u32] into r149 as [field; 3u32]; + cast 0field r3[0u32].siblings[14u32] r144 into r150 as [field; 3u32]; + ternary r148 r149[0u32] r150[0u32] into r151; + ternary r148 r149[1u32] r150[1u32] into r152; + ternary r148 r149[2u32] r150[2u32] into r153; + cast r151 r152 r153 into r154 as [field; 3u32]; + hash.psd4 r154 into r155 as field; + is.eq r3[0u32].siblings[15u32] 0field into r156; + div r3[0u32].leaf_index 16384u32 into r157; + rem r157 2u32 into r158; + is.eq r158 0u32 into r159; + cast 0field r155 r3[0u32].siblings[15u32] into r160 as [field; 3u32]; + cast 0field r3[0u32].siblings[15u32] r155 into r161 as [field; 3u32]; + ternary r159 r160[0u32] r161[0u32] into r162; + ternary r159 r160[1u32] r161[1u32] into r163; + ternary r159 r160[2u32] r161[2u32] into r164; + cast r162 r163 r164 into r165 as [field; 3u32]; + hash.psd4 r165 into r166 as field; + ternary r156 r155 r166 into r167; + ternary r156 14u32 15u32 into r168; + ternary r145 r144 r167 into r169; + ternary r145 13u32 r168 into r170; + ternary r134 r133 r169 into r171; + ternary r134 12u32 r170 into r172; + ternary r123 r122 r171 into r173; + ternary r123 11u32 r172 into r174; + ternary r112 r111 r173 into r175; + ternary r112 10u32 r174 into r176; + ternary r101 r100 r175 into r177; + ternary r101 9u32 r176 into r178; + ternary r90 r89 r177 into r179; + ternary r90 8u32 r178 into r180; + ternary r79 r78 r179 into r181; + ternary r79 7u32 r180 into r182; + ternary r68 r67 r181 into r183; + ternary r68 6u32 r182 into r184; + ternary r57 r56 r183 into r185; + ternary r57 5u32 r184 into r186; + ternary r46 r45 r185 into r187; + ternary r46 4u32 r186 into r188; + ternary r35 r34 r187 into r189; + ternary r35 3u32 r188 into r190; + ternary r24 r23 r189 into r191; + ternary r24 2u32 r190 into r192; + ternary r13 r12 r191 into r193; + ternary r13 1u32 r192 into r194; + rem r3[1u32].leaf_index 2u32 into r195; + is.eq r195 0u32 into r196; + cast 1field r3[1u32].siblings[0u32] r3[1u32].siblings[1u32] into r197 as [field; 3u32]; + cast 1field r3[1u32].siblings[1u32] r3[1u32].siblings[0u32] into r198 as [field; 3u32]; + ternary r196 r197[0u32] r198[0u32] into r199; + ternary r196 r197[1u32] r198[1u32] into r200; + ternary r196 r197[2u32] r198[2u32] into r201; + cast r199 r200 r201 into r202 as [field; 3u32]; + hash.psd4 r202 into r203 as field; + is.eq r3[1u32].siblings[2u32] 0field into r204; + div r3[1u32].leaf_index 2u32 into r205; + rem r205 2u32 into r206; + is.eq r206 0u32 into r207; + cast 0field r203 r3[1u32].siblings[2u32] into r208 as [field; 3u32]; + cast 0field r3[1u32].siblings[2u32] r203 into r209 as [field; 3u32]; + ternary r207 r208[0u32] r209[0u32] into r210; + ternary r207 r208[1u32] r209[1u32] into r211; + ternary r207 r208[2u32] r209[2u32] into r212; + cast r210 r211 r212 into r213 as [field; 3u32]; + hash.psd4 r213 into r214 as field; + is.eq r3[1u32].siblings[3u32] 0field into r215; + div r3[1u32].leaf_index 4u32 into r216; + rem r216 2u32 into r217; + is.eq r217 0u32 into r218; + cast 0field r214 r3[1u32].siblings[3u32] into r219 as [field; 3u32]; + cast 0field r3[1u32].siblings[3u32] r214 into r220 as [field; 3u32]; + ternary r218 r219[0u32] r220[0u32] into r221; + ternary r218 r219[1u32] r220[1u32] into r222; + ternary r218 r219[2u32] r220[2u32] into r223; + cast r221 r222 r223 into r224 as [field; 3u32]; + hash.psd4 r224 into r225 as field; + is.eq r3[1u32].siblings[4u32] 0field into r226; + div r3[1u32].leaf_index 8u32 into r227; + rem r227 2u32 into r228; + is.eq r228 0u32 into r229; + cast 0field r225 r3[1u32].siblings[4u32] into r230 as [field; 3u32]; + cast 0field r3[1u32].siblings[4u32] r225 into r231 as [field; 3u32]; + ternary r229 r230[0u32] r231[0u32] into r232; + ternary r229 r230[1u32] r231[1u32] into r233; + ternary r229 r230[2u32] r231[2u32] into r234; + cast r232 r233 r234 into r235 as [field; 3u32]; + hash.psd4 r235 into r236 as field; + is.eq r3[1u32].siblings[5u32] 0field into r237; + div r3[1u32].leaf_index 16u32 into r238; + rem r238 2u32 into r239; + is.eq r239 0u32 into r240; + cast 0field r236 r3[1u32].siblings[5u32] into r241 as [field; 3u32]; + cast 0field r3[1u32].siblings[5u32] r236 into r242 as [field; 3u32]; + ternary r240 r241[0u32] r242[0u32] into r243; + ternary r240 r241[1u32] r242[1u32] into r244; + ternary r240 r241[2u32] r242[2u32] into r245; + cast r243 r244 r245 into r246 as [field; 3u32]; + hash.psd4 r246 into r247 as field; + is.eq r3[1u32].siblings[6u32] 0field into r248; + div r3[1u32].leaf_index 32u32 into r249; + rem r249 2u32 into r250; + is.eq r250 0u32 into r251; + cast 0field r247 r3[1u32].siblings[6u32] into r252 as [field; 3u32]; + cast 0field r3[1u32].siblings[6u32] r247 into r253 as [field; 3u32]; + ternary r251 r252[0u32] r253[0u32] into r254; + ternary r251 r252[1u32] r253[1u32] into r255; + ternary r251 r252[2u32] r253[2u32] into r256; + cast r254 r255 r256 into r257 as [field; 3u32]; + hash.psd4 r257 into r258 as field; + is.eq r3[1u32].siblings[7u32] 0field into r259; + div r3[1u32].leaf_index 64u32 into r260; + rem r260 2u32 into r261; + is.eq r261 0u32 into r262; + cast 0field r258 r3[1u32].siblings[7u32] into r263 as [field; 3u32]; + cast 0field r3[1u32].siblings[7u32] r258 into r264 as [field; 3u32]; + ternary r262 r263[0u32] r264[0u32] into r265; + ternary r262 r263[1u32] r264[1u32] into r266; + ternary r262 r263[2u32] r264[2u32] into r267; + cast r265 r266 r267 into r268 as [field; 3u32]; + hash.psd4 r268 into r269 as field; + is.eq r3[1u32].siblings[8u32] 0field into r270; + div r3[1u32].leaf_index 128u32 into r271; + rem r271 2u32 into r272; + is.eq r272 0u32 into r273; + cast 0field r269 r3[1u32].siblings[8u32] into r274 as [field; 3u32]; + cast 0field r3[1u32].siblings[8u32] r269 into r275 as [field; 3u32]; + ternary r273 r274[0u32] r275[0u32] into r276; + ternary r273 r274[1u32] r275[1u32] into r277; + ternary r273 r274[2u32] r275[2u32] into r278; + cast r276 r277 r278 into r279 as [field; 3u32]; + hash.psd4 r279 into r280 as field; + is.eq r3[1u32].siblings[9u32] 0field into r281; + div r3[1u32].leaf_index 256u32 into r282; + rem r282 2u32 into r283; + is.eq r283 0u32 into r284; + cast 0field r280 r3[1u32].siblings[9u32] into r285 as [field; 3u32]; + cast 0field r3[1u32].siblings[9u32] r280 into r286 as [field; 3u32]; + ternary r284 r285[0u32] r286[0u32] into r287; + ternary r284 r285[1u32] r286[1u32] into r288; + ternary r284 r285[2u32] r286[2u32] into r289; + cast r287 r288 r289 into r290 as [field; 3u32]; + hash.psd4 r290 into r291 as field; + is.eq r3[1u32].siblings[10u32] 0field into r292; + div r3[1u32].leaf_index 512u32 into r293; + rem r293 2u32 into r294; + is.eq r294 0u32 into r295; + cast 0field r291 r3[1u32].siblings[10u32] into r296 as [field; 3u32]; + cast 0field r3[1u32].siblings[10u32] r291 into r297 as [field; 3u32]; + ternary r295 r296[0u32] r297[0u32] into r298; + ternary r295 r296[1u32] r297[1u32] into r299; + ternary r295 r296[2u32] r297[2u32] into r300; + cast r298 r299 r300 into r301 as [field; 3u32]; + hash.psd4 r301 into r302 as field; + is.eq r3[1u32].siblings[11u32] 0field into r303; + div r3[1u32].leaf_index 1024u32 into r304; + rem r304 2u32 into r305; + is.eq r305 0u32 into r306; + cast 0field r302 r3[1u32].siblings[11u32] into r307 as [field; 3u32]; + cast 0field r3[1u32].siblings[11u32] r302 into r308 as [field; 3u32]; + ternary r306 r307[0u32] r308[0u32] into r309; + ternary r306 r307[1u32] r308[1u32] into r310; + ternary r306 r307[2u32] r308[2u32] into r311; + cast r309 r310 r311 into r312 as [field; 3u32]; + hash.psd4 r312 into r313 as field; + is.eq r3[1u32].siblings[12u32] 0field into r314; + div r3[1u32].leaf_index 2048u32 into r315; + rem r315 2u32 into r316; + is.eq r316 0u32 into r317; + cast 0field r313 r3[1u32].siblings[12u32] into r318 as [field; 3u32]; + cast 0field r3[1u32].siblings[12u32] r313 into r319 as [field; 3u32]; + ternary r317 r318[0u32] r319[0u32] into r320; + ternary r317 r318[1u32] r319[1u32] into r321; + ternary r317 r318[2u32] r319[2u32] into r322; + cast r320 r321 r322 into r323 as [field; 3u32]; + hash.psd4 r323 into r324 as field; + is.eq r3[1u32].siblings[13u32] 0field into r325; + div r3[1u32].leaf_index 4096u32 into r326; + rem r326 2u32 into r327; + is.eq r327 0u32 into r328; + cast 0field r324 r3[1u32].siblings[13u32] into r329 as [field; 3u32]; + cast 0field r3[1u32].siblings[13u32] r324 into r330 as [field; 3u32]; + ternary r328 r329[0u32] r330[0u32] into r331; + ternary r328 r329[1u32] r330[1u32] into r332; + ternary r328 r329[2u32] r330[2u32] into r333; + cast r331 r332 r333 into r334 as [field; 3u32]; + hash.psd4 r334 into r335 as field; + is.eq r3[1u32].siblings[14u32] 0field into r336; + div r3[1u32].leaf_index 8192u32 into r337; + rem r337 2u32 into r338; + is.eq r338 0u32 into r339; + cast 0field r335 r3[1u32].siblings[14u32] into r340 as [field; 3u32]; + cast 0field r3[1u32].siblings[14u32] r335 into r341 as [field; 3u32]; + ternary r339 r340[0u32] r341[0u32] into r342; + ternary r339 r340[1u32] r341[1u32] into r343; + ternary r339 r340[2u32] r341[2u32] into r344; + cast r342 r343 r344 into r345 as [field; 3u32]; + hash.psd4 r345 into r346 as field; + is.eq r3[1u32].siblings[15u32] 0field into r347; + div r3[1u32].leaf_index 16384u32 into r348; + rem r348 2u32 into r349; + is.eq r349 0u32 into r350; + cast 0field r346 r3[1u32].siblings[15u32] into r351 as [field; 3u32]; + cast 0field r3[1u32].siblings[15u32] r346 into r352 as [field; 3u32]; + ternary r350 r351[0u32] r352[0u32] into r353; + ternary r350 r351[1u32] r352[1u32] into r354; + ternary r350 r351[2u32] r352[2u32] into r355; + cast r353 r354 r355 into r356 as [field; 3u32]; + hash.psd4 r356 into r357 as field; + ternary r347 r346 r357 into r358; + ternary r347 14u32 15u32 into r359; + ternary r336 r335 r358 into r360; + ternary r336 13u32 r359 into r361; + ternary r325 r324 r360 into r362; + ternary r325 12u32 r361 into r363; + ternary r314 r313 r362 into r364; + ternary r314 11u32 r363 into r365; + ternary r303 r302 r364 into r366; + ternary r303 10u32 r365 into r367; + ternary r292 r291 r366 into r368; + ternary r292 9u32 r367 into r369; + ternary r281 r280 r368 into r370; + ternary r281 8u32 r369 into r371; + ternary r270 r269 r370 into r372; + ternary r270 7u32 r371 into r373; + ternary r259 r258 r372 into r374; + ternary r259 6u32 r373 into r375; + ternary r248 r247 r374 into r376; + ternary r248 5u32 r375 into r377; + ternary r237 r236 r376 into r378; + ternary r237 4u32 r377 into r379; + ternary r226 r225 r378 into r380; + ternary r226 3u32 r379 into r381; + ternary r215 r214 r380 into r382; + ternary r215 2u32 r381 into r383; + ternary r204 r203 r382 into r384; + ternary r204 1u32 r383 into r385; + assert.eq r193 r384; + assert.eq r194 r385; + cast r2.owner into r386 as field; + is.eq r3[0u32].leaf_index r3[1u32].leaf_index into r387; + is.eq r3[0u32].leaf_index 0u32 into r388; + lt r386 r3[0u32].siblings[0u32] into r389; + and r387 r388 into r390; + not r390 into r391; + or r389 r391 into r392; + assert.eq r392 true; + not r388 into r393; + pow 2u32 r194 into r394; + sub r394 1u32 into r395; + and r387 r393 into r396; + not r396 into r397; + is.eq r3[0u32].leaf_index r395 into r398; + or r398 r397 into r399; + assert.eq r399 true; + gt r386 r3[0u32].siblings[0u32] into r400; + or r400 r397 into r401; + assert.eq r401 true; + not r387 into r402; + gt r386 r3[0u32].siblings[0u32] into r403; + not r402 into r404; + or r403 r404 into r405; + assert.eq r405 true; + lt r386 r3[1u32].siblings[0u32] into r406; + or r406 r404 into r407; + assert.eq r407 true; + lte r3[1u32].leaf_index r395 into r408; + or r408 r404 into r409; + assert.eq r409 true; + add r3[0u32].leaf_index 1u32 into r410; + is.eq r410 r3[1u32].leaf_index into r411; + or r411 r404 into r412; + assert.eq r412 true; + sub r2.amount r1 into r413; + cast r2.owner r413 into r414 as Token.record; + cast aleo1mnldqsfrwayzfep3t9zusu4y7yknsdhfwx76v5pajla35mrqn5xsvvurhy r1 r2.owner r0 into r415 as ComplianceRecord.record; + async transfer_private_to_public r193 r0 r1 into r416; + output r415 as ComplianceRecord.record; + output r414 as Token.record; + output r416 as test_usdcx_stablecoin.aleo/transfer_private_to_public.future; + +finalize transfer_private_to_public: + input r0 as field.public; + input r1 as address.public; + input r2 as u128.public; + get pause[true] into r3; + assert.eq r3 false; + get test_usdcx_freezelist.aleo/freeze_list_root[1u8] into r4; + get test_usdcx_freezelist.aleo/block_height_window[true] into r5; + is.neq r4 r0 into r6; + branch.eq r6 false to end_then_0_6; + get test_usdcx_freezelist.aleo/freeze_list_root[2u8] into r7; + assert.eq r0 r7; + get test_usdcx_freezelist.aleo/root_updated_height[true] into r8; + add r8 r5 into r9; + gt r9 block.height into r10; + assert.eq r10 true; + branch.eq true true to end_otherwise_0_7; + position end_then_0_6; + position end_otherwise_0_7; + get.or_use test_usdcx_freezelist.aleo/freeze_list[r1] false into r11; + assert.eq r11 false; + get.or_use balances[r1] 0u128 into r12; + add r12 r2 into r13; + set r13 into balances[r1]; + +function set_pause_status: + input r0 as boolean.private; + async set_pause_status r0 self.caller into r1; + output r1 as test_usdcx_stablecoin.aleo/set_pause_status.future; + +finalize set_pause_status: + input r0 as boolean.public; + input r1 as address.public; + get address_to_role[r1] into r2; + and r2 4u16 into r3; + is.eq r3 4u16 into r4; + assert.eq r4 true; + set r0 into pause[true]; + +function join: + input r0 as Token.record; + input r1 as Token.record; + add r0.amount r1.amount into r2; + cast r0.owner r2 into r3 as Token.record; + output r3 as Token.record; + +function split: + input r0 as Token.record; + input r1 as u128.private; + cast r0.owner r1 into r2 as Token.record; + sub r0.amount r1 into r3; + cast r0.owner r3 into r4 as Token.record; + output r2 as Token.record; + output r4 as Token.record; + +function transfer_private_with_creds: + input r0 as address.private; + input r1 as u128.private; + input r2 as Token.record; + input r3 as Credentials.record; + sub r2.amount r1 into r4; + cast r2.owner r4 into r5 as Token.record; + cast r0 r1 into r6 as Token.record; + cast aleo1mnldqsfrwayzfep3t9zusu4y7yknsdhfwx76v5pajla35mrqn5xsvvurhy r1 r2.owner r0 into r7 as ComplianceRecord.record; + cast r3.owner r3.freeze_list_root into r8 as Credentials.record; + async transfer_private_with_creds r3.freeze_list_root into r9; + output r7 as ComplianceRecord.record; + output r5 as Token.record; + output r6 as Token.record; + output r8 as Credentials.record; + output r9 as test_usdcx_stablecoin.aleo/transfer_private_with_creds.future; + +finalize transfer_private_with_creds: + input r0 as field.public; + get pause[true] into r1; + assert.eq r1 false; + get test_usdcx_freezelist.aleo/freeze_list_root[1u8] into r2; + get test_usdcx_freezelist.aleo/block_height_window[true] into r3; + is.neq r2 r0 into r4; + branch.eq r4 false to end_then_0_8; + get test_usdcx_freezelist.aleo/freeze_list_root[2u8] into r5; + assert.eq r0 r5; + get test_usdcx_freezelist.aleo/root_updated_height[true] into r6; + add r6 r3 into r7; + gt r7 block.height into r8; + assert.eq r8 true; + branch.eq true true to end_otherwise_0_9; + position end_then_0_8; + position end_otherwise_0_9; + +function update_token_info: + input r0 as u128.public; + input r1 as u128.public; + input r2 as u128.public; + async update_token_info r0 r1 r2 self.caller into r3; + output r3 as test_usdcx_stablecoin.aleo/update_token_info.future; + +finalize update_token_info: + input r0 as u128.public; + input r1 as u128.public; + input r2 as u128.public; + input r3 as address.public; + get address_to_role[r3] into r4; + is.eq r4 8u16 into r5; + assert.eq r5 true; + get token_info[true] into r6; + cast r0 r1 r6.decimals r6.supply r2 into r7 as TokenInfo; + set r7 into token_info[true]; + +constructor: + is.eq edition 0u16 into r0; + branch.eq r0 false to end_then_0_10; + assert.eq program_owner aleo17pmtmh8t7zwh0qfj8z0cmg0rqt4rtg4t85dy5ldrst5u0c4yvufq3gl9lf; + branch.eq true true to end_otherwise_0_11; + position end_then_0_10; + cast checksum edition into r1 as ChecksumEdition; + hash.bhp256 r1 into r2 as field; + cast test_usdcx_stablecoin.aleo r2 into r3 as WalletSigningOpId; + hash.bhp256 r3 into r4 as field; + contains test_usdcx_multisig_core.aleo/completed_signing_ops[r4] into r5; + assert.eq r5 true; + position end_otherwise_0_11; diff --git a/sdk/python/tests/test_programs.py b/sdk/python/tests/test_programs.py index 6381db3..930bcf3 100644 --- a/sdk/python/tests/test_programs.py +++ b/sdk/python/tests/test_programs.py @@ -1,5 +1,17 @@ +from pathlib import Path + from aleo.mainnet import Program, Process, PrivateKey, Identifier, ProgramID, Value, Authorization +FIXTURES = Path(__file__).parent / "fixtures" + + +def fixture_source(name: str) -> str: + return (FIXTURES / name).read_text() + + +def fixture_program(name: str) -> Program: + return Program.from_source(fixture_source(name)) + def test_credits_program_parse(): p = Program.credits() @@ -20,3 +32,103 @@ def test_authorize_transfer_public(): assert auth is not None # round-trip the authorization assert str(Authorization.from_json(auth.to_json())) == str(auth) + + +def test_function_inputs_external_struct_id(): + # the template's transfer_private takes [MerkleProof; 2u32] where MerkleProof + # is imported from freezelist.aleo; struct_id must be the struct name, not the + # program name + p = fixture_program("compliant_token_template.aleo") + array_input = p.get_function_inputs("transfer_private")[3] + assert array_input["type"] == "array" + assert array_input["element_type"]["struct_id"] == "MerkleProof" + + +class TestIsArc20: + def test_compliant_program(self): + assert fixture_program("arc20_token.aleo").is_arc20() + + def test_arc20_is_not_arc22(self): + # transfer signatures differ between the two standards + assert not fixture_program("arc20_token.aleo").is_arc22() + + def test_deployed_testnet_token(self): + # https://testnet.explorer.provable.com/program/test_arc20_eth.aleo + p = fixture_program("test_arc20_eth.aleo") + assert p.is_arc20() + assert not p.is_arc22() + + def test_credits_is_not_arc20(self): + assert not Program.credits().is_arc20() + + def test_wrong_amount_type(self): + src = fixture_source("arc20_token.aleo").replace("u128", "u64") + assert not Program.from_source(src).is_arc20() + + def test_missing_function(self): + src = fixture_source("arc20_token.aleo").replace("function join:", "function join_tokens:") + assert not Program.from_source(src).is_arc20() + + def test_missing_all_views(self): + src = fixture_source("arc20_token.aleo").split("view balance_of:")[0] + assert not Program.from_source(src).is_arc20() + + def test_missing_one_view(self): + src = fixture_source("arc20_token.aleo").replace("view symbol:", "view symbol_of:") + assert not Program.from_source(src).is_arc20() + + def test_wrong_view_signature(self): + src = fixture_source("arc20_token.aleo").replace( + "view balance_of:\n input r0 as address.public;", + "view balance_of:\n input r0 as field.public;", + ) + assert not Program.from_source(src).is_arc20() + + def test_foreign_futures(self): + # future outputs pointing at another program do not satisfy the interface + src = fixture_source("arc20_token.aleo").replace("arc20_token.aleo/", "credits.aleo/") + assert not Program.from_source(src).is_arc20() + + def test_public_record_owner(self): + src = fixture_source("arc20_token.aleo").replace( + "owner as address.private", "owner as address.public" + ) + assert not Program.from_source(src).is_arc20() + + def test_wrong_record_name(self): + src = fixture_source("arc20_token.aleo").replace("Token", "Coupon") + assert not Program.from_source(src).is_arc20() + + +class TestIsArc22: + def test_compliant_program(self): + # the extra `token_id` entry on the Token record is permitted by the `..` + assert fixture_program("arc22_token.aleo").is_arc22() + + def test_arc22_is_not_arc20(self): + assert not fixture_program("arc22_token.aleo").is_arc20() + + def test_leo_compiled_template(self): + # Leo-compiled template importing MerkleProof from freezelist.aleo + p = fixture_program("compliant_token_template.aleo") + assert p.is_arc22() + assert not p.is_arc20() + + def test_deployed_testnet_near_miss(self): + # matches all IARC22 function/record signatures but declares no view + # functions, so it is not compliant + # https://api.provable.com/v2/testnet/programs/test_usdcx_stablecoin.aleo + p = fixture_program("test_usdcx_stablecoin.aleo") + assert not p.is_arc22() + assert not p.is_arc20() + + def test_credits_is_not_arc22(self): + assert not Program.credits().is_arc22() + + def test_wrong_merkle_proof_shape(self): + src = fixture_source("arc22_token.aleo").replace("[field; 16u32]", "[field; 8u32]") + assert not Program.from_source(src).is_arc22() + + def test_missing_compliance_record(self): + src = fixture_source("arc22_token.aleo").replace("ComplianceRecord", "AuditRecord") + assert not Program.from_source(src).is_arc22() diff --git a/sdk/src/programs/program.rs b/sdk/src/programs/program.rs index e6dcc26..40ed782 100644 --- a/sdk/src/programs/program.rs +++ b/sdk/src/programs/program.rs @@ -32,6 +32,200 @@ use std::{ops::Deref, str::FromStr}; #[pyclass(frozen)] pub struct Program(ProgramNative); +/// The required signature of an interface function or view function, expressed in the +/// canonical `.aleo` bytecode type notation (e.g. "address.public", "Token.record"). +/// The special output marker "future" matches any future type, since a future's locator +/// embeds the id of the program being checked. +struct InterfaceFunction { + name: &'static str, + inputs: &'static [&'static str], + outputs: &'static [&'static str], +} + +const FUTURE: &str = "future"; + +/// Input marker for the ARC-22 Merkle proof array, which is matched structurally rather +/// than by exact type string since the MerkleProof struct may be local or imported. +const MERKLE_PROOFS: &str = "[MerkleProof; 2u32].private"; + +/// The functions required by the ARC-20 token interface (IARC20). +const ARC20_FUNCTIONS: &[InterfaceFunction] = &[ + InterfaceFunction { + name: "transfer_public", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "transfer_private", + inputs: &["Token.record", "address.private", "u128.private"], + outputs: &["Token.record", "Token.record"], + }, + InterfaceFunction { + name: "transfer_private_to_public", + inputs: &["Token.record", "address.public", "u128.public"], + outputs: &["Token.record", FUTURE], + }, + InterfaceFunction { + name: "transfer_public_to_private", + inputs: &["address.private", "u128.public"], + outputs: &["Token.record", FUTURE], + }, + InterfaceFunction { + name: "transfer_public_as_signer", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "transfer_from_public", + inputs: &["address.public", "address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "transfer_from_public_to_private", + inputs: &["address.public", "address.private", "u128.public"], + outputs: &["Token.record", FUTURE], + }, + InterfaceFunction { + name: "approve_public", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "unapprove_public", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "join", + inputs: &["Token.record", "Token.record"], + outputs: &["Token.record"], + }, + InterfaceFunction { + name: "split", + inputs: &["Token.record", "u128.private"], + outputs: &["Token.record", "Token.record"], + }, +]; + +/// The view functions required by both the ARC-20 (IARC20) and ARC-22 (IARC22) token +/// interfaces. View function inputs and outputs are always public. +const ARC20_VIEWS: &[InterfaceFunction] = &[ + InterfaceFunction { + name: "balance_of", + inputs: &["address.public"], + outputs: &["u128.public"], + }, + InterfaceFunction { + name: "allowance", + inputs: &["address.public", "address.public"], + outputs: &["u128.public"], + }, + InterfaceFunction { + name: "supply", + inputs: &[], + outputs: &["u128.public"], + }, + InterfaceFunction { + name: "max_supply", + inputs: &[], + outputs: &["u128.public"], + }, + InterfaceFunction { + name: "decimals", + inputs: &[], + outputs: &["u8.public"], + }, + InterfaceFunction { + name: "name", + inputs: &[], + outputs: &["identifier.public"], + }, + InterfaceFunction { + name: "symbol", + inputs: &[], + outputs: &["identifier.public"], + }, +]; + +/// The functions required by the ARC-22 compliant token interface (IARC22). +const ARC22_FUNCTIONS: &[InterfaceFunction] = &[ + InterfaceFunction { + name: "approve_public", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "unapprove_public", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "transfer_public", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "transfer_private", + inputs: &[ + "address.private", + "u128.private", + "Token.record", + MERKLE_PROOFS, + ], + outputs: &[ + "ComplianceRecord.record", + "Token.record", + "Token.record", + FUTURE, + ], + }, + InterfaceFunction { + name: "transfer_private_to_public", + inputs: &[ + "address.public", + "u128.public", + "Token.record", + MERKLE_PROOFS, + ], + outputs: &["ComplianceRecord.record", "Token.record", FUTURE], + }, + InterfaceFunction { + name: "transfer_public_to_private", + inputs: &["address.private", "u128.public"], + outputs: &["ComplianceRecord.record", "Token.record", FUTURE], + }, + InterfaceFunction { + name: "transfer_from_public", + inputs: &["address.public", "address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "transfer_from_public_to_private", + inputs: &["address.public", "address.private", "u128.public"], + outputs: &["ComplianceRecord.record", "Token.record", FUTURE], + }, + InterfaceFunction { + name: "transfer_public_as_signer", + inputs: &["address.public", "u128.public"], + outputs: &[FUTURE], + }, + InterfaceFunction { + name: "join", + inputs: &["Token.record", "Token.record"], + outputs: &["Token.record"], + }, + InterfaceFunction { + name: "split", + inputs: &["Token.record", "u128.private"], + outputs: &["Token.record", "Token.record"], + }, +]; + +/// The members of the MerkleProof struct required by the ARC-22 interface, where +/// the siblings array is sized by `MAX_TREE_DEPTH + 1` with `MAX_TREE_DEPTH = 15`. +const ARC22_MERKLE_PROOF_MEMBERS: &[(&str, &str)] = + &[("siblings", "[field; 16u32]"), ("leaf_index", "u32")]; + #[pymethods] impl Program { /// Creates a program from source code. @@ -199,6 +393,176 @@ impl Program { fn address(&self) -> anyhow::Result
{ self.0.id().to_address().map(Address::from) } + + /// Returns true if the program implements the ARC-20 fungible token interface (IARC20). + /// + /// This checks that the program defines a `Token` record with an `amount: u128` entry + /// (additional entries are permitted, per the interface's open record definition) and + /// that every function and view function required by ARC-20 is present with the exact + /// input and output signature defined by the standard. + /// + /// See https://github.com/ProvableHQ/ARCs/blob/master/arc-0020/README.md + fn is_arc20(&self) -> bool { + self.record_has_entries("Token", &[("amount", "u128")]) + && ARC20_FUNCTIONS + .iter() + .all(|function| self.matches_function(function)) + && ARC20_VIEWS.iter().all(|view| self.matches_view(view)) + } + + /// Returns true if the program implements the ARC-22 compliant token interface (IARC22). + /// + /// This checks that the program defines `Token` and `ComplianceRecord` records with the + /// entries required by the standard (additional entries are permitted, per the + /// interface's open record definitions), and that every function and view function + /// required by ARC-22 is present with the exact input and output signature defined by + /// the standard. The `MerkleProof` struct used by the private transfer functions may be + /// declared locally (in which case its shape must match the standard exactly) or + /// imported from another program such as a freeze list registry. + /// + /// Note: this checks the token interface (IARC22) only. The freeze list registry + /// interface (IARC22Freezelist) is typically implemented by a separate program and is + /// not required for a token program to be considered ARC-22 compliant. + /// + /// See https://github.com/ProvableHQ/ARCs/blob/master/arc-0022/README.md + fn is_arc22(&self) -> bool { + self.record_has_entries("Token", &[("amount", "u128")]) + && self.record_has_entries( + "ComplianceRecord", + &[ + ("amount", "u128"), + ("sender", "address"), + ("recipient", "address"), + ], + ) + && ARC22_FUNCTIONS + .iter() + .all(|function| self.matches_function(function)) + && ARC20_VIEWS.iter().all(|view| self.matches_view(view)) + } +} + +// Private helpers backing the ARC-20/ARC-22 interface checks (not exposed to Python). +impl Program { + // Check that a function exists with the exact interface signature. + fn matches_function(&self, interface_function: &InterfaceFunction) -> bool { + let Ok(name) = IdentifierNative::from_str(interface_function.name) else { + return false; + }; + let Some(function) = self.0.functions().get(&name) else { + return false; + }; + let inputs = function.input_types(); + let outputs = function.output_types(); + inputs.len() == interface_function.inputs.len() + && outputs.len() == interface_function.outputs.len() + && inputs + .iter() + .zip(interface_function.inputs) + .all(|(input, expected)| { + if *expected == MERKLE_PROOFS { + self.is_merkle_proof_array(input) + } else { + input.to_string() == *expected + } + }) + && outputs + .iter() + .zip(interface_function.outputs) + .all(|(output, expected)| { + if *expected == FUTURE { + // A `Final` output must be the function's own future — a future pointing + // at another program's function does not satisfy the interface. + matches!(output, ValueType::Future(locator) + if locator.program_id() == self.0.id() + && locator.resource().to_string() == interface_function.name) + } else { + output.to_string() == *expected + } + }) + } + + // Check that a function input is a private two-element array of the ARC-22 MerkleProof + // struct. The struct may be declared locally, in which case its shape must match the + // standard exactly, or imported from another program (e.g. a freeze list registry), + // whose definition cannot be resolved from this program alone. + fn is_merkle_proof_array(&self, input: &ValueType) -> bool { + let ValueType::Private(PlaintextType::Array(array)) = input else { + return false; + }; + if **array.length() != 2u32 { + return false; + } + match array.next_element_type() { + PlaintextType::Struct(name) => { + name.to_string() == "MerkleProof" + && self.struct_matches("MerkleProof", ARC22_MERKLE_PROOF_MEMBERS) + } + PlaintextType::ExternalStruct(locator) => { + locator.resource().to_string() == "MerkleProof" + } + _ => false, + } + } + + // Check that a view function exists with the exact interface signature. + fn matches_view(&self, interface_view: &InterfaceFunction) -> bool { + let Ok(name) = IdentifierNative::from_str(interface_view.name) else { + return false; + }; + let Some(view) = self.0.views().get(&name) else { + return false; + }; + let inputs = view.input_types(); + let outputs = view.output_types(); + inputs.len() == interface_view.inputs.len() + && outputs.len() == interface_view.outputs.len() + && inputs + .iter() + .zip(interface_view.inputs) + .all(|(input, expected)| input.to_string() == *expected) + && outputs + .iter() + .zip(interface_view.outputs) + .all(|(output, expected)| output.to_string() == *expected) + } + + // Check that a record exists with a private owner, containing at least the given + // private entries; additional entries are permitted, matching the `..` in interface + // record definitions. + fn record_has_entries(&self, record_name: &str, entries: &[(&str, &str)]) -> bool { + let Ok(name) = IdentifierNative::from_str(record_name) else { + return false; + }; + let Ok(record) = self.0.get_record(&name) else { + return false; + }; + if !record.owner().is_private() { + return false; + } + entries.iter().all(|(entry_name, entry_type)| { + record.entries().iter().any(|(name, ty)| { + name.to_string() == *entry_name + && matches!(ty, EntryType::Private(plaintext) if plaintext.to_string() == *entry_type) + }) + }) + } + + // Check that a struct exists with exactly the given members in order. + fn struct_matches(&self, struct_name: &str, members: &[(&str, &str)]) -> bool { + let Ok(name) = IdentifierNative::from_str(struct_name) else { + return false; + }; + let Ok(struct_) = self.0.get_struct(&name) else { + return false; + }; + struct_.members().len() == members.len() + && struct_.members().iter().zip(members).all( + |((name, ty), (expected_name, expected_type))| { + name.to_string() == *expected_name && ty.to_string() == *expected_type + }, + ) + } } impl Deref for Program { @@ -260,9 +624,9 @@ fn plaintext_input_to_dict<'py>( d.set_item("name", n)?; } d.set_item("type", "struct")?; - d.set_item("struct_id", locator.name().to_string())?; + d.set_item("struct_id", locator.resource().to_string())?; // External structs live in another program; best-effort expansion only if locally available. - if let Ok(members) = struct_members_list(py, program, &locator.name().to_string()) { + if let Ok(members) = struct_members_list(py, program, &locator.resource().to_string()) { d.set_item("members", members)?; } }