{"content":{"title":"OpenBuild Starknet Bootcamp任务3：Starknet Foundry合约测试代码错误修复及部署和交互测试","body":"# OpenBuild Starknet Bootcamp任务3：Starknet Foundry合约测试代码错误修复及部署和交互测试\r\n\r\n## 1 任务要求\r\n\r\n1. 基于 [Ownable contract with SnFoundry](https://github.com/gianalarcon/Ownable-contract-snFoundry)， 在 **tests/test_ownable.cairo** 文件上完成测试。当前包含一个老版本的测试，需要升级到 v0.12.0 or v0.13.0并修复错误，所有的测试必须通过 `snforge test` ，你可参考 [Voting contract](https://github.com/gianalarcon/vote-contract) ，也可查看[snfoundry-book](https://foundry-rs.github.io/starknet-foundry/index.html)。\r\n2. 部署到测试，并与 [Ownable components](https://github.com/gianalarcon/ownable-components) 合约交互\r\n\r\n## 2 工具安装\r\n\r\n- **scarb**\r\n\r\n```bash\r\n# 安装插件\r\n$ asdf plugin add scarb\r\n\r\n# 查看所有可安装版本\r\n$ asdf list-all scarb\r\n......\r\n0.7.0\r\n2.3.0\r\n2.3.1\r\n2.4.0\r\n2.4.1\r\n\r\n# 安装指定版本\r\n$ asdf install scarb 2.4.1\r\n\r\n# 全局使用版本\r\n$ asdf global scarb 2.4.1\r\n\r\n# 查看版本号\r\n$ scarb --version\r\nscarb 2.4.1 (c93ee6249 2023-12-21)\r\ncairo: 2.4.1 (https://crates.io/crates/cairo-lang-compiler/2.4.1)\r\nsierra: 1.4.0\r\n```\r\n\r\n- **snforge**\r\n\r\n```bash\r\n# 安装插件\r\n$ asdf plugin add starknet-foundry\r\n\r\n# 查看所有可安装版本\r\n$ asdf list-all starknet-foundry\r\n......\r\n0.10.2\r\n0.11.0\r\n0.12.0\r\n0.13.0\r\n0.13.1\r\n\r\n# 安装指定版本\r\n$ asdf install starknet-foundry 0.13.1\r\n\r\n# 全局使用版本\r\n$ asdf global starknet-foundry 0.13.1\r\n\r\n# 查看版本号\r\n$ snforge --version\r\nsnforge 0.13.1\r\n\r\n$ sncast --version\r\nsncast 0.13.1\r\n```\r\n\r\n## 3 项目创建及错误修复\r\n\r\n### 3.1 创建项目\r\n\r\n```bash\r\n# 项目初始化\r\n$ snforge init ownable_contract_snfoundry\r\nCreated `ownable_contract_snfoundry` package.\r\n\r\n# 编译\r\n$ scarb build\r\n   Compiling ownable_contract_snfoundry v0.1.0 (/root/StarknetHome/ownable_contract_snfoundry/Scarb.toml)\r\n    Finished release target(s) in 1 second\r\n    \r\n# 测试\r\n$ snforge test\r\n   Compiling ownable_contract_snfoundry v0.1.0 (/root/StarknetHome/ownable_contract_snfoundry/Scarb.toml)\r\n    Finished release target(s) in 1 second\r\nCollected 2 test(s) from ownable_contract_snfoundry package\r\nRunning 0 test(s) from src/\r\nRunning 2 test(s) from tests/\r\n[PASS] tests::test_contract::test_cannot_increase_balance_with_zero_value, gas: ~1842\r\n[PASS] tests::test_contract::test_increase_balance, gas: ~3068\r\nTests: 2 passed, 0 failed, 0 skipped, 0 ignored, 0 filtered out\r\n```\r\n\r\n- `Scarb.toml`文件内容为\r\n\r\n```toml\r\n[package]\r\nname = \"ownable_contract_snfoundry\"\r\nversion = \"0.1.0\"\r\nedition = \"2023_10\"\r\n\r\n# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html\r\n\r\n[dependencies]\r\nsnforge_std = { git = \"https://github.com/foundry-rs/starknet-foundry\", tag = \"v0.13.1\" }\r\nstarknet = \"2.4.1\"\r\n\r\n[[target.starknet-contract]]\r\ncasm = true\r\n```\r\n\r\n### 3.2 拷贝合约和测试文件\r\n\r\n- 将`src/lib.cairo`中的代码替换为：https://github.com/gianalarcon/Ownable-contract-snFoundry/blob/main/src/lib.cairo\r\n\r\n```rust\r\nuse core::traits::TryInto;\r\nuse starknet::ContractAddress;\r\n\r\n#[starknet::interface]\r\ntrait IData<T> {\r\n    fn get_data(self: @T) -> felt252;\r\n    fn set_data(ref self: T, new_value: felt252);\r\n    fn other_func(self: @T, other_contract: ContractAddress) -> felt252;\r\n}\r\n\r\n#[starknet::interface]\r\ntrait OwnableTrait<T> {\r\n    fn transfer_ownership(ref self: T, new_owner: ContractAddress);\r\n    fn read_owner(self: @T) -> ContractAddress;\r\n}\r\n\r\n#[starknet::contract]\r\nmod ownable {\r\n    use starknet::get_caller_address;\r\n    use super::{ContractAddress, IData, IDataDispatcherTrait, IDataDispatcher, OwnableTrait};\r\n\r\n    #[storage]\r\n    struct Storage {\r\n        owner: ContractAddress,\r\n        data: felt252,\r\n    }\r\n\r\n    #[event]\r\n    #[derive(Drop, starknet::Event)]\r\n    enum Event {\r\n        OwnershipTransferred: OwnershipTransferred,\r\n    }\r\n\r\n    #[derive(Drop, starknet::Event)]\r\n    struct OwnershipTransferred {\r\n        #[key]\r\n        prev_owner: ContractAddress,\r\n        #[key]\r\n        new_owner: ContractAddress,\r\n    }\r\n\r\n    #[constructor]\r\n    fn constructor(ref self: ContractState, initial_owner: ContractAddress) {\r\n        self.owner.write(initial_owner);\r\n        self.data.write(1);\r\n    // Any variable of the storage that is not initialized\r\n    // will have default value -> data = 0.\r\n    }\r\n\r\n    #[external(v0)]\r\n    impl OwnableDataImpl of IData<ContractState> {\r\n        fn other_func(self: @ContractState, other_contract: ContractAddress) -> felt252 {\r\n            IDataDispatcher { contract_address: other_contract }.get_data()\r\n        }\r\n\r\n        fn get_data(self: @ContractState) -> felt252 {\r\n            self.data.read()\r\n        }\r\n\r\n        fn set_data(ref self: ContractState, new_value: felt252) {\r\n            self.only_owner();\r\n            self.data.write(new_value);\r\n        }\r\n    }\r\n\r\n    #[external(v0)]\r\n    impl OwnableTraitImpl of OwnableTrait<ContractState> {\r\n        fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) {\r\n            self.only_owner();\r\n            let prev_owner = self.owner.read();\r\n            self.owner.write(new_owner);\r\n\r\n            self.emit(OwnershipTransferred { prev_owner, new_owner });\r\n        }\r\n\r\n        fn read_owner(self: @ContractState) -> ContractAddress {\r\n            self.owner.read()\r\n        }\r\n    }\r\n\r\n    #[generate_trait]\r\n    impl PrivateMethods of PrivateMethodsTrait {\r\n        fn only_owner(self: @ContractState) {\r\n            let caller = get_caller_address();\r\n            assert(caller == self.owner.read(), 'Caller is not the owner');\r\n        }\r\n    }\r\n}\r\n```\r\n\r\n- 将`tests/test_contract.cairo`测试文件内容替换为：https://github.com/gianalarcon/Ownable-contract-snFoundry/blob/main/tests/test_ownable.cairo\r\n\r\n```bash\r\n// This test were working with snFoundry version v0.7.0. You task is to enable this tests using snFoundry version v0.12.0 or v0.13.0\r\nuse starknet::{ContractAddress, Into, TryInto, OptionTrait};\r\nuse starknet::syscalls::deploy_syscall;\r\nuse result::ResultTrait;\r\nuse array::{ArrayTrait, SpanTrait};\r\nuse snforge_std::{declare, ContractClassTrait};\r\nuse snforge_std::io::{FileTrait, read_txt};\r\nuse snforge_std::{start_prank, stop_prank};\r\nuse snforge_std::{start_mock_call, stop_mock_call};\r\n\r\nuse ownable_starknet::{OwnableTraitDispatcher, OwnableTraitDispatcherTrait};\r\nuse ownable_starknet::{IDataSafeDispatcher, IDataSafeDispatcherTrait};\r\n\r\nmod Errors {\r\n    const INVALID_OWNER: felt252 = 'Caller is not the owner';\r\n    const INVALID_DATA: felt252 = 'Invalid data';\r\n}\r\n\r\nmod Accounts {\r\n    use traits::TryInto;\r\n    use starknet::ContractAddress;\r\n\r\n    fn admin() -> ContractAddress {\r\n        'admin'.try_into().unwrap()\r\n    }\r\n    fn new_admin() -> ContractAddress {\r\n        'new_admin'.try_into().unwrap()\r\n    }\r\n    fn bad_guy() -> ContractAddress {\r\n        'bad_guy'.try_into().unwrap()\r\n    }\r\n}\r\n\r\nfn deploy_contract(name: felt252) -> ContractAddress {\r\n    // let account = Accounts::admin();\r\n    let contract = declare(name);\r\n\r\n    let file = FileTrait::new('data/calldata.txt');\r\n    let calldata = read_txt(@file);\r\n    //deploy contract\r\n    contract.deploy(@calldata).unwrap()\r\n}\r\n\r\n#[test]\r\nfn test_construct_with_admin() {\r\n    let contract_address = deploy_contract('ownable');\r\n    let dispatcher = OwnableTraitDispatcher { contract_address };\r\n    let owner = dispatcher.read_owner();\r\n    assert(owner == Accounts::admin(), Errors::INVALID_OWNER);\r\n}\r\n\r\n#[test]\r\nfn test_transfer_ownership() {\r\n    let contract_address = deploy_contract('ownable');\r\n    let dispatcher = OwnableTraitDispatcher { contract_address };\r\n    start_prank(contract_address, Accounts::admin());\r\n    dispatcher.transfer_ownership(Accounts::new_admin());\r\n\r\n    assert(dispatcher.read_owner() == Accounts::new_admin(), Errors::INVALID_OWNER);\r\n}\r\n\r\n#[test]\r\n#[should_panic(expected: ('Caller is not the owner',))]\r\nfn test_transfer_ownership_bad_guy() {\r\n    let contract_address = deploy_contract('ownable');\r\n    let dispatcher = OwnableTraitDispatcher { contract_address };\r\n    start_prank(contract_address, Accounts::bad_guy());\r\n    dispatcher.transfer_ownership(Accounts::bad_guy());\r\n\r\n    assert(dispatcher.read_owner() == Accounts::bad_guy(), Errors::INVALID_OWNER);\r\n}\r\n\r\n#[test]\r\nfn test_data_mock_call_get_data() {\r\n    let contract_address = deploy_contract('ownable');\r\n    let safe_dispatcher = IDataSafeDispatcher { contract_address };\r\n    let mock_ret_data = 100;\r\n    start_mock_call(contract_address, 'get_data', mock_ret_data);\r\n    start_prank(contract_address, Accounts::admin());\r\n    safe_dispatcher.set_data(20);\r\n    let data = safe_dispatcher.get_data().unwrap();\r\n    assert(data == mock_ret_data, Errors::INVALID_DATA);\r\n    stop_mock_call(contract_address, 'get_data');\r\n\r\n    let data2 = safe_dispatcher.get_data().unwrap();\r\n    assert(data2 == 20, Errors::INVALID_DATA);\r\n    stop_prank(contract_address);\r\n}\r\n```\r\n\r\n### 3.3 修改测试文件错误\r\n\r\n#### （1）错误1：引用包路径错误\r\n\r\n```rust\r\n// 修改前\r\nuse snforge_std::io::{FileTrait, read_txt};\r\n\r\n// 修改后\r\nuse snforge_std::fs::{FileTrait, read_txt};\r\n```\r\n\r\n#### （2）错误2：参数类型错误\r\n\r\n```rust\r\n// 修改前\r\n// Unexpected argument type. Expected: \"snforge_std::cheatcodes::CheatTarget\", found: \"core::starknet::contract_address::ContractAddress\".\r\nstart_prank(contract_address, Accounts::admin());\r\n\r\n// 修改后\r\n// use snforge_std::{start_prank, stop_prank, cheatcodes::CheatTarget};\r\nstart_prank(CheatTarget::One(contract_address), Accounts::admin());\r\n```\r\n\r\n### 3.4 测试用例执行验证\r\n\r\n```\r\n$ snforge test\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/IlKFvgPq65884d5185eb0.png)\r\n\r\n## 4 测试网部署\r\n\r\n### 4.1 部署[ownable_contract_snfoundry](https://github.com/bityoume/OpenBuildStarknet/tree/main/ownable_contract_snfoundry)合约\r\n\r\n> 使用`Argent`账号进行部署，关于钱包创建方法参看：https://learnblockchain.cn/article/7093\r\n\r\n#### （1）声明合约\r\n\r\n```bash\r\n$ . .env_a \r\n\r\n$ starkli declare target/dev/ownable_contract_snfoundry_ownable.contract_class.json --compiler-version 2.4.0\r\n\r\nEnter keystore password: \r\nDeclaring Cairo 1 class: 0x0061754ea57dc5c76e0a40f76b9414a99958695535eff09c3283bf4a0f7d1861\r\nCompiling Sierra class to CASM with compiler version 2.4.0...\r\nCASM class hash: 0x01cf30830a36b80f72e5a6da74186f5a9ffcee82806307c5be8316881dd4598c\r\nContract declaration transaction: 0x0248c9a033267aaa9b1f3d8757ad27cd2b9080c64b9971ad58971d46c15d7c0f\r\nClass hash declared:\r\n0x0061754ea57dc5c76e0a40f76b9414a99958695535eff09c3283bf4a0f7d1861\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/aPP8ZvtY65884d702d37c.png)\r\n\r\n#### （2）部署合约\r\n\r\n```bash\r\n$  starkli deploy 0x0061754ea57dc5c76e0a40f76b9414a99958695535eff09c3283bf4a0f7d1861 0x05E51CAF456A394D4ED02c4e0f373d8A162851c492d382F74822b10AaD11300d\r\n\r\nEnter keystore password: \r\nDeploying class 0x0061754ea57dc5c76e0a40f76b9414a99958695535eff09c3283bf4a0f7d1861 with salt 0x01d8784d2215068e92c5cc2fa646fb3ddf7627584467795205b8f26f71cb69b3...\r\nThe contract will be deployed at address 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105\r\nContract deployment transaction: 0x077c2f47dfd136a766736394660cdd41e199dff9060642aa9ed00dedfafcb67c\r\nContract deployed:\r\n0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/To7wurwE65884d7fbc8ea.png)\r\n\r\n### 4.2 部署[Ownable components](https://github.com/gianalarcon/ownable-components)合约\r\n\r\n> 使用`Braavos`账号部署\r\n\r\n```bash\r\n$ git clone git@github.com:gianalarcon/ownable-components.git\r\n\r\n$ cd ownable-components\r\n\r\n$ source .env_b \r\n\r\n$ scarb build\r\n   Compiling ownable_project v0.1.0 (/root/StarknetHome/ownable-components/Scarb.toml)\r\n    Finished release target(s) in 1 second\r\n    \r\n$ starkli declare target/dev/ownable_project_ownable_contract.contract_class.json --compiler-version 2.4.0\r\nEnter keystore password: \r\nDeclaring Cairo 1 class: 0x03ce5c0ea09e68c01fc8d5b9f7aeae319af3929c81d701b2c158b3e28f66a970\r\nCompiling Sierra class to CASM with compiler version 2.4.0...\r\nCASM class hash: 0x00bec2e19ce9af001758e96dbd2b41d6917c214a607be022320d206bf780293f\r\nContract declaration transaction: 0x07bbbc6521f19f18daf53e129ae31d58394739a9eef5a5405910e3328e457750\r\nClass hash declared:\r\n0x03ce5c0ea09e68c01fc8d5b9f7aeae319af3929c81d701b2c158b3e28f66a970\r\n\r\n$ starkli deploy 0x03ce5c0ea09e68c01fc8d5b9f7aeae319af3929c81d701b2c158b3e28f66a970 0x00b05390123e1e3749ae040834342eefd541f96e210b50f4ff6de8e8dd37b08d\r\nEnter keystore password: \r\nDeploying class 0x03ce5c0ea09e68c01fc8d5b9f7aeae319af3929c81d701b2c158b3e28f66a970 with salt 0x002872f5d1c20eb84422d3c56a25b591e0c18d1cd1891e1e61aec1649cdd0acc...\r\nThe contract will be deployed at address 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33\r\nContract deployment transaction: 0x037744b9b2b909637730ec3677a76a68b9dfc7358f9a539578f719e1a1d6eb1f\r\nContract deployed:\r\n0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/07PIuiXx65884d9167dd2.png)\r\n\r\n### 4.3 部署信息汇总\r\n\r\n| 钱包类型 | 部署钱包地址                                                 | 部署合约地址                                                 | 部署合约代码                                                 |\r\n| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\r\n| Argent   | 0x05E51CAF456A394D4ED02c4e0f373d8A162851c492d382F74822b10AaD11300d | 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105 | [ownable_contract_snfoundry](https://github.com/bityoume/OpenBuildStarknet/tree/main/ownable_contract_snfoundry) |\r\n| Braavos  | 0x00b05390123e1e3749ae040834342eefd541f96e210b50f4ff6de8e8dd37b08d | 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 | [Ownable components](https://github.com/gianalarcon/ownable-components) |\r\n\r\n## 5 合约交互测试\r\n\r\n### 5.1 获取钱包所有者\r\n\r\n```bash\r\n$ starkli call 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105 read_owner\r\n[\r\n    \"0x05e51caf456a394d4ed02c4e0f373d8a162851c492d382f74822b10aad11300d\"\r\n]\r\n\r\n$ starkli call 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 owner\r\n[\r\n    \"0x00b05390123e1e3749ae040834342eefd541f96e210b50f4ff6de8e8dd37b08d\"\r\n]\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/4ZNTSXNA65884da348ff0.png)\r\n\r\n### 5.2 ArgentX帐号成功修改自己的数据\r\n\r\n```bash\r\n$ starkli call 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105 get_data\r\n[\r\n    \"0x0000000000000000000000000000000000000000000000000000000000000001\"\r\n]\r\n\r\n$ starkli invoke 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105 set_data 0x123\r\nEnter keystore password: \r\nInvoke transaction: 0x02c171741868c946f98be3e4aa1d2107e4482c408b27470e99a36df393e19ff5\r\n\r\n$ starkli call 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105 get_data\r\n[\r\n    \"0x0000000000000000000000000000000000000000000000000000000000000123\"\r\n]\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/tM4pWWUR65884db0e81a1.png)\r\n\r\n### 5.3 Braavos帐号成功修改自己的数据\r\n\r\n```bash\r\n$ starkli call 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 get_data\r\n[\r\n    \"0x0000000000000000000000000000000000000000000000000000000000000001\"\r\n]\r\n\r\n$ starkli invoke 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 set_data 0x456\r\nEnter keystore password: \r\nInvoke transaction: 0x02d0b54f5cd412b1bc73cf387d0909244f4f870a0f9eb60c4aa265458d74e9ac\r\n\r\n$ starkli call 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 get_data\r\n[\r\n    \"0x0000000000000000000000000000000000000000000000000000000000000456\"\r\n]\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/LiXYg8wz65884dc20802d.png)\r\n\r\n### 5.4 ArgentX帐号修改Braavos帐号创建的合约数据失败\r\n\r\n```bash\r\n$ starkli call 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105 other_func 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33\r\n[\r\n    \"0x0000000000000000000000000000000000000000000000000000000000000456\"\r\n]\r\n\r\n$ starkli invoke 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 set_data 0x789\r\nEnter keystore password: \r\nError: code=ContractError, message=\"Contract error\"\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/mN5ujgOv65884dcdba72d.png)\r\n\r\n### 5.5 Braavos帐号将合约所有权转移给ArgentX帐号\r\n\r\n```bash\r\n# 转移前帐号归属\r\n$ starkli call 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 owner\r\n[\r\n    \"0x00b05390123e1e3749ae040834342eefd541f96e210b50f4ff6de8e8dd37b08d\"\r\n]\r\n\r\n# 转移帐号所有权\r\n$ starkli invoke 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 transfer_ownership 0x05E51CAF456A394D4ED02c4e0f373d8A162851c492d382F74822b10AaD11300d\r\nEnter keystore password: \r\nInvoke transaction: 0x03c9cb58d3c5426008e09d257a9ab15a88d272c6933072bb035aae9e1c117d04\r\n\r\n# 转移后帐号归属\r\n$ starkli call 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 owner\r\n[\r\n    \"0x05e51caf456a394d4ed02c4e0f373d8a162851c492d382f74822b10aad11300d\"\r\n]\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/G2VSsBh965884ddaaf01c.png)\r\n\r\n### 5.6 ArgentX帐号再次修改帐号Braavos的合约数据成功\r\n\r\n```bash\r\n$ starkli invoke 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33 set_data 0x789\r\nEnter keystore password: \r\nInvoke transaction: 0x05d96084aa237aceab74030ce187e4ccc1d97fb7f62fc6d3c3dd447ab9aeb8f6\r\n\r\n$ starkli call 0x064144d7d422e06a5587e3bf6e3dffedee57f2010937a9645aaf7aab76c97105 other_func 0x01d6c6da546bd75cea9f2c1ecbb2cb8c16fb464515f5fadfbba44fb73c66ed33\r\n[\r\n    \"0x0000000000000000000000000000000000000000000000000000000000000789\"\r\n]\r\n```\r\n\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2023/12/BpivQ12Y65884de7f236e.png)"},"author":{"user":"https://learnblockchain.cn/people/932","address":null},"history":"bafkreibwkjtxx65dwmgyk5nydyfqbcrk37gpn76mcru2ee2nojf5wboym4","timestamp":1703432348,"version":1}