-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add deny list transactional tests (#15706)
## Description This PR replaces the deny list simtest with transactional tests, which are much easier to inspect and validate. To make errors easier to visualize and update, this PR also introduces a new function in the test adapter that can replace known addresses and IDs with names/fake ids in the error string. ## Test Plan CI --- If your changes are not user-facing and do not break anything, you can skip the following section. Otherwise, please briefly describe what has changed under the Release Notes section. ### Type of Change (Check all that apply) - [ ] protocol change - [ ] user-visible impact - [ ] breaking change for a client SDKs - [ ] breaking change for FNs (FN binary must upgrade) - [ ] breaking change for validators or node operators (must upgrade binaries) - [ ] breaking change for on-chain data layout - [ ] necessitate either a data wipe or data migration ### Release notes
- Loading branch information
Showing
23 changed files
with
530 additions
and
430 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
62 changes: 62 additions & 0 deletions
62
crates/sui-adapter-transactional-tests/tests/deny_list/coin_deny_and_undeny.exp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
processed 14 tasks | ||
|
||
init: | ||
A: object(0,0), B: object(0,1) | ||
|
||
task 1 'publish'. lines 12-38: | ||
created: object(1,0), object(1,1), object(1,2), object(1,3), object(1,4), object(1,5) | ||
mutated: object(0,0) | ||
gas summary: computation_cost: 1000000, storage_cost: 18316000, storage_rebate: 0, non_refundable_storage_fee: 0 | ||
|
||
task 2 'view-object'. lines 40-40: | ||
1,0::regulated_coin | ||
|
||
task 3 'view-object'. lines 42-42: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: sui::coin::Coin<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,1)}}, balance: sui::balance::Balance<test::regulated_coin::REGULATED_COIN> {value: 10000u64}} | ||
|
||
task 4 'view-object'. lines 44-44: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::CoinMetadata<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,2)}}, decimals: 9u8, name: std::string::String {bytes: vector[82u8, 69u8, 71u8, 85u8, 76u8, 65u8, 84u8, 69u8, 68u8, 95u8, 67u8, 79u8, 73u8, 78u8]}, symbol: std::ascii::String {bytes: vector[82u8, 67u8]}, description: std::string::String {bytes: vector[65u8, 32u8, 110u8, 101u8, 119u8, 32u8, 114u8, 101u8, 103u8, 117u8, 108u8, 97u8, 116u8, 101u8, 100u8, 32u8, 99u8, 111u8, 105u8, 110u8]}, icon_url: std::option::Option<sui::url::Url> {vec: vector[]}} | ||
|
||
task 5 'view-object'. lines 46-46: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: sui::coin::DenyCap<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,3)}}} | ||
|
||
task 6 'view-object'. lines 48-48: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::RegulatedCoinMetadata<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,4)}}, coin_metadata_object: sui::object::ID {bytes: fake(1,2)}, deny_cap_object: sui::object::ID {bytes: fake(1,3)}} | ||
|
||
task 7 'view-object'. lines 50-52: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::TreasuryCap<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,5)}}, total_supply: sui::balance::Supply<test::regulated_coin::REGULATED_COIN> {value: 10000u64}} | ||
|
||
task 8 'run'. lines 53-55: | ||
created: object(8,0) | ||
mutated: object(0,0), object(1,1) | ||
gas summary: computation_cost: 1000000, storage_cost: 3936800, storage_rebate: 2437776, non_refundable_storage_fee: 24624 | ||
|
||
task 9 'run'. lines 56-58: | ||
created: object(9,0), object(9,1) | ||
mutated: object(_), 0x0000000000000000000000000000000000000000000000000000000000000403, object(0,0), object(1,3) | ||
gas summary: computation_cost: 1000000, storage_cost: 11415200, storage_rebate: 2723688, non_refundable_storage_fee: 27512 | ||
|
||
task 10 'transfer-object'. lines 59-61: | ||
Error: Error checking transaction input objects: AddressDeniedForCoin { address: @B, coin_type: "object(1,0)::regulated_coin::REGULATED_COIN" } | ||
|
||
task 11 'run'. lines 62-64: | ||
Error: Error checking transaction input objects: AddressDeniedForCoin { address: @B, coin_type: "object(1,0)::regulated_coin::REGULATED_COIN" } | ||
|
||
task 12 'run'. lines 65-67: | ||
mutated: object(_), 0x0000000000000000000000000000000000000000000000000000000000000403, object(0,0), object(1,3), object(9,1) | ||
deleted: object(9,0) | ||
gas summary: computation_cost: 1000000, storage_cost: 9522800, storage_rebate: 11301048, non_refundable_storage_fee: 114152 | ||
|
||
task 13 'transfer-object'. lines 68-68: | ||
mutated: object(0,1), object(8,0) | ||
gas summary: computation_cost: 1000000, storage_cost: 2462400, storage_rebate: 1459656, non_refundable_storage_fee: 14744 |
68 changes: 68 additions & 0 deletions
68
crates/sui-adapter-transactional-tests/tests/deny_list/coin_deny_and_undeny.move
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// This test verifies the basic e2e work flow of coin deny list. | ||
// A newly created regulated coin type should come with the deny cap object. | ||
// Coin isser can use the deny cap to deny addresses, which will no longer be able to | ||
// transfer the coin or use it in Move calls. | ||
// Undeny the address will restore the original behavior. | ||
|
||
//# init --accounts A B --addresses test=0x0 | ||
|
||
//# publish --sender A | ||
module test::regulated_coin { | ||
use std::option; | ||
use sui::coin; | ||
use sui::transfer; | ||
use sui::tx_context; | ||
use sui::tx_context::TxContext; | ||
|
||
struct REGULATED_COIN has drop {} | ||
|
||
fun init(otw: REGULATED_COIN, ctx: &mut TxContext) { | ||
let (treasury_cap, deny_cap, metadata) = coin::create_regulated_currency( | ||
otw, | ||
9, | ||
b"RC", | ||
b"REGULATED_COIN", | ||
b"A new regulated coin", | ||
option::none(), | ||
ctx | ||
); | ||
let coin = coin::mint(&mut treasury_cap, 10000, ctx); | ||
transfer::public_transfer(coin, tx_context::sender(ctx)); | ||
transfer::public_transfer(deny_cap, tx_context::sender(ctx)); | ||
transfer::public_freeze_object(treasury_cap); | ||
transfer::public_freeze_object(metadata); | ||
} | ||
} | ||
|
||
//# view-object 1,0 | ||
|
||
//# view-object 1,1 | ||
|
||
//# view-object 1,2 | ||
|
||
//# view-object 1,3 | ||
|
||
//# view-object 1,4 | ||
|
||
//# view-object 1,5 | ||
|
||
// Transfer away the newly minted coin works normally. | ||
//# run sui::pay::split_and_transfer --args object(1,1) 1 @B --type-args test::regulated_coin::REGULATED_COIN --sender A | ||
|
||
// Deny account B. | ||
//# run sui::coin::deny_list_add --args object(0x403) object(1,3) @B --type-args test::regulated_coin::REGULATED_COIN --sender A | ||
|
||
// Try transfer the coin from B. This should now be denied. | ||
//# transfer-object 8,0 --sender B --recipient A | ||
|
||
// Try using the coin in a Move call. This should also be denied. | ||
//# run sui::pay::split_and_transfer --args object(8,0) 1 @A --type-args test::regulated_coin::REGULATED_COIN --sender B | ||
|
||
// Undeny account B. | ||
//# run sui::coin::deny_list_remove --args object(0x403) object(1,3) @B --type-args test::regulated_coin::REGULATED_COIN --sender A | ||
|
||
// This time the transfer should work. | ||
//# transfer-object 8,0 --sender B --recipient A |
74 changes: 74 additions & 0 deletions
74
crates/sui-adapter-transactional-tests/tests/deny_list/coin_deny_multiple_per_module.exp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
processed 16 tasks | ||
|
||
init: | ||
A: object(0,0) | ||
|
||
task 1 'publish'. lines 9-62: | ||
created: object(1,0), object(1,1), object(1,2), object(1,3), object(1,4), object(1,5), object(1,6), object(1,7), object(1,8), object(1,9), object(1,10) | ||
mutated: object(0,0) | ||
gas summary: computation_cost: 1000000, storage_cost: 33082800, storage_rebate: 0, non_refundable_storage_fee: 0 | ||
|
||
task 2 'view-object'. lines 64-64: | ||
1,0::{first_coin, second_coin} | ||
|
||
task 3 'view-object'. lines 66-66: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: sui::coin::Coin<test::first_coin::FIRST_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,1)}}, balance: sui::balance::Balance<test::first_coin::FIRST_COIN> {value: 10000u64}} | ||
|
||
task 4 'view-object'. lines 68-68: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: sui::coin::Coin<test::second_coin::SECOND_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,2)}}, balance: sui::balance::Balance<test::second_coin::SECOND_COIN> {value: 10000u64}} | ||
|
||
task 5 'view-object'. lines 70-70: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::CoinMetadata<test::first_coin::FIRST_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,3)}}, decimals: 9u8, name: std::string::String {bytes: vector[82u8, 69u8, 71u8, 85u8, 76u8, 65u8, 84u8, 69u8, 68u8, 95u8, 67u8, 79u8, 73u8, 78u8]}, symbol: std::ascii::String {bytes: vector[82u8, 67u8]}, description: std::string::String {bytes: vector[65u8, 32u8, 110u8, 101u8, 119u8, 32u8, 114u8, 101u8, 103u8, 117u8, 108u8, 97u8, 116u8, 101u8, 100u8, 32u8, 99u8, 111u8, 105u8, 110u8]}, icon_url: std::option::Option<sui::url::Url> {vec: vector[]}} | ||
|
||
task 6 'view-object'. lines 72-72: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::CoinMetadata<test::second_coin::SECOND_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,4)}}, decimals: 9u8, name: std::string::String {bytes: vector[82u8, 69u8, 71u8, 85u8, 76u8, 65u8, 84u8, 69u8, 68u8, 95u8, 67u8, 79u8, 73u8, 78u8]}, symbol: std::ascii::String {bytes: vector[82u8, 67u8]}, description: std::string::String {bytes: vector[65u8, 32u8, 110u8, 101u8, 119u8, 32u8, 114u8, 101u8, 103u8, 117u8, 108u8, 97u8, 116u8, 101u8, 100u8, 32u8, 99u8, 111u8, 105u8, 110u8]}, icon_url: std::option::Option<sui::url::Url> {vec: vector[]}} | ||
|
||
task 7 'view-object'. lines 74-74: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: sui::coin::DenyCap<test::first_coin::FIRST_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,5)}}} | ||
|
||
task 8 'view-object'. lines 76-76: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: sui::coin::DenyCap<test::second_coin::SECOND_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,6)}}} | ||
|
||
task 9 'view-object'. lines 78-78: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::RegulatedCoinMetadata<test::first_coin::FIRST_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,7)}}, coin_metadata_object: sui::object::ID {bytes: fake(1,3)}, deny_cap_object: sui::object::ID {bytes: fake(1,5)}} | ||
|
||
task 10 'view-object'. lines 80-80: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::RegulatedCoinMetadata<test::second_coin::SECOND_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,8)}}, coin_metadata_object: sui::object::ID {bytes: fake(1,4)}, deny_cap_object: sui::object::ID {bytes: fake(1,6)}} | ||
|
||
task 11 'view-object'. lines 82-82: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::TreasuryCap<test::first_coin::FIRST_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,9)}}, total_supply: sui::balance::Supply<test::first_coin::FIRST_COIN> {value: 10000u64}} | ||
|
||
task 12 'view-object'. lines 84-86: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::TreasuryCap<test::second_coin::SECOND_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,10)}}, total_supply: sui::balance::Supply<test::second_coin::SECOND_COIN> {value: 10000u64}} | ||
|
||
task 13 'run'. lines 87-89: | ||
created: object(13,0), object(13,1) | ||
mutated: object(_), 0x0000000000000000000000000000000000000000000000000000000000000403, object(0,0), object(1,5) | ||
gas summary: computation_cost: 1000000, storage_cost: 11293600, storage_rebate: 2663496, non_refundable_storage_fee: 26904 | ||
|
||
task 14 'transfer-object'. lines 90-92: | ||
Error: Error checking transaction input objects: AddressDeniedForCoin { address: @A, coin_type: "object(1,0)::first_coin::FIRST_COIN" } | ||
|
||
task 15 'transfer-object'. lines 93-93: | ||
mutated: object(0,0), object(1,2) | ||
gas summary: computation_cost: 1000000, storage_cost: 2416800, storage_rebate: 2392632, non_refundable_storage_fee: 24168 |
93 changes: 93 additions & 0 deletions
93
crates/sui-adapter-transactional-tests/tests/deny_list/coin_deny_multiple_per_module.move
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// Copyright (c) Mysten Labs, Inc. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
// This test creates multiple coin types in the same module, and show that deny actions on one type does not affect | ||
// the other type. | ||
|
||
//# init --accounts A --addresses test=0x0 | ||
|
||
//# publish --sender A | ||
module test::first_coin { | ||
use std::option; | ||
use sui::coin; | ||
use sui::transfer; | ||
use sui::tx_context; | ||
use sui::tx_context::TxContext; | ||
|
||
struct FIRST_COIN has drop {} | ||
|
||
fun init(otw: FIRST_COIN, ctx: &mut TxContext) { | ||
let (treasury_cap, deny_cap, metadata) = coin::create_regulated_currency( | ||
otw, | ||
9, | ||
b"RC", | ||
b"REGULATED_COIN", | ||
b"A new regulated coin", | ||
option::none(), | ||
ctx | ||
); | ||
let coin = coin::mint(&mut treasury_cap, 10000, ctx); | ||
transfer::public_transfer(coin, tx_context::sender(ctx)); | ||
transfer::public_transfer(deny_cap, tx_context::sender(ctx)); | ||
transfer::public_freeze_object(treasury_cap); | ||
transfer::public_freeze_object(metadata); | ||
} | ||
} | ||
|
||
module test::second_coin { | ||
use std::option; | ||
use sui::coin; | ||
use sui::transfer; | ||
use sui::tx_context; | ||
use sui::tx_context::TxContext; | ||
|
||
struct SECOND_COIN has drop {} | ||
|
||
fun init(otw: SECOND_COIN, ctx: &mut TxContext) { | ||
let (treasury_cap, deny_cap, metadata) = coin::create_regulated_currency( | ||
otw, | ||
9, | ||
b"RC", | ||
b"REGULATED_COIN", | ||
b"A new regulated coin", | ||
option::none(), | ||
ctx | ||
); | ||
let coin = coin::mint(&mut treasury_cap, 10000, ctx); | ||
transfer::public_transfer(coin, tx_context::sender(ctx)); | ||
transfer::public_transfer(deny_cap, tx_context::sender(ctx)); | ||
transfer::public_freeze_object(treasury_cap); | ||
transfer::public_freeze_object(metadata); | ||
} | ||
} | ||
|
||
//# view-object 1,0 | ||
|
||
//# view-object 1,1 | ||
|
||
//# view-object 1,2 | ||
|
||
//# view-object 1,3 | ||
|
||
//# view-object 1,4 | ||
|
||
//# view-object 1,5 | ||
|
||
//# view-object 1,6 | ||
|
||
//# view-object 1,7 | ||
|
||
//# view-object 1,8 | ||
|
||
//# view-object 1,9 | ||
|
||
//# view-object 1,10 | ||
|
||
// Deny account A for FIRST_COIN. | ||
//# run sui::coin::deny_list_add --args object(0x403) object(1,5) @A --type-args test::first_coin::FIRST_COIN --sender A | ||
|
||
// Sending away first coin from A should fail. | ||
//# transfer-object 1,1 --sender A --recipient A | ||
|
||
// Sending away second coin from A should not be affected, and hence will succeed. | ||
//# transfer-object 1,2 --sender A --recipient A |
59 changes: 59 additions & 0 deletions
59
crates/sui-adapter-transactional-tests/tests/deny_list/coin_deny_tto.exp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
processed 13 tasks | ||
|
||
init: | ||
A: object(0,0) | ||
|
||
task 1 'publish'. lines 8-52: | ||
created: object(1,0), object(1,1), object(1,2), object(1,3), object(1,4), object(1,5), object(1,6) | ||
mutated: object(0,0) | ||
gas summary: computation_cost: 1000000, storage_cost: 21766400, storage_rebate: 0, non_refundable_storage_fee: 0 | ||
|
||
task 2 'view-object'. lines 54-54: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: test::regulated_coin::Wallet {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,0)}}} | ||
|
||
task 3 'view-object'. lines 56-56: | ||
1,1::regulated_coin | ||
|
||
task 4 'view-object'. lines 58-58: | ||
Owner: Account Address ( fake(1,0) ) | ||
Version: 2 | ||
Contents: sui::coin::Coin<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,2)}}, balance: sui::balance::Balance<test::regulated_coin::REGULATED_COIN> {value: 10000u64}} | ||
|
||
task 5 'view-object'. lines 60-60: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::CoinMetadata<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,3)}}, decimals: 9u8, name: std::string::String {bytes: vector[82u8, 69u8, 71u8, 85u8, 76u8, 65u8, 84u8, 69u8, 68u8, 95u8, 67u8, 79u8, 73u8, 78u8]}, symbol: std::ascii::String {bytes: vector[82u8, 67u8]}, description: std::string::String {bytes: vector[65u8, 32u8, 110u8, 101u8, 119u8, 32u8, 114u8, 101u8, 103u8, 117u8, 108u8, 97u8, 116u8, 101u8, 100u8, 32u8, 99u8, 111u8, 105u8, 110u8]}, icon_url: std::option::Option<sui::url::Url> {vec: vector[]}} | ||
|
||
task 6 'view-object'. lines 62-62: | ||
Owner: Account Address ( A ) | ||
Version: 2 | ||
Contents: sui::coin::DenyCap<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,4)}}} | ||
|
||
task 7 'view-object'. lines 64-64: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::RegulatedCoinMetadata<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,5)}}, coin_metadata_object: sui::object::ID {bytes: fake(1,3)}, deny_cap_object: sui::object::ID {bytes: fake(1,4)}} | ||
|
||
task 8 'view-object'. lines 66-68: | ||
Owner: Immutable | ||
Version: 2 | ||
Contents: sui::coin::TreasuryCap<test::regulated_coin::REGULATED_COIN> {id: sui::object::UID {id: sui::object::ID {bytes: fake(1,6)}}, total_supply: sui::balance::Supply<test::regulated_coin::REGULATED_COIN> {value: 10000u64}} | ||
|
||
task 9 'run'. lines 69-71: | ||
created: object(9,0), object(9,1) | ||
mutated: object(_), 0x0000000000000000000000000000000000000000000000000000000000000403, object(0,0), object(1,4) | ||
gas summary: computation_cost: 1000000, storage_cost: 11415200, storage_rebate: 2723688, non_refundable_storage_fee: 27512 | ||
|
||
task 10 'run'. lines 72-74: | ||
Error: Error checking transaction input objects: AddressDeniedForCoin { address: @A, coin_type: "object(1,1)::regulated_coin::REGULATED_COIN" } | ||
|
||
task 11 'run'. lines 75-77: | ||
mutated: object(_), 0x0000000000000000000000000000000000000000000000000000000000000403, object(0,0), object(1,4), object(9,1) | ||
deleted: object(9,0) | ||
gas summary: computation_cost: 1000000, storage_cost: 9522800, storage_rebate: 11301048, non_refundable_storage_fee: 114152 | ||
|
||
task 12 'run'. lines 78-78: | ||
mutated: object(0,0), object(1,0), object(1,2) | ||
gas summary: computation_cost: 1000000, storage_cost: 3807600, storage_rebate: 3769524, non_refundable_storage_fee: 38076 |
Oops, something went wrong.