Skip to content

Commit a58f063

Browse files
authored
More integration tests (#103)
* Add configurable test actor * WIP configurable actor tests * Add operator_data to MintParams in the basic token actor * Don't blindly flush state after minting Doing this can unintentionally revert to the pre-hook state if the receiver hook carried out further operations on the balance received * test: receiver hook burns incoming tokens after mint * MintParams formatting * wip make minting aware of changed state after receiver hook returns * wip better state reloading mechanism * more common stuff * single-actor tests * keep TestAction and ActionParams as part of test_actor * duplicate MintParams in common to avoid linking in the token actor everywhere can only link against one actor for shared structs, because of the invoke methods using un-mangled names (causing collisions at link time if more than one is included) * wip multi-actor tests * don't explode the test actor if transfer within receiver hook fails original recipient just keeps the tokens in this case, instead of rejecting the transfer they originally received * add test to mint tokens and then transfer inside the receiver hook * update Transfer and TransferFrom to have the same post-hook state handling as Mint does * return Transfer call result in test actor the caller can check for success or failure of the transfer and also has the TransferReturn data available for use * add transfer->hook transfer->accept/burn tests * update transfer_tokens test to use the common helpers * improve Token::replace and make public * abort with an error instead of ignoring calls to Accept or Reject in an Action * rename get_balance to token_balance to avoid confusion with native token balance * separate individual frc46 tests into blocks * add call_method_ok and mint_tokens_ok helpers to assert success and reduce test case size * add token balance assertion helpers to further compress test case code * add more balance asserts and check the more complex transfer results * remove unnecessary comment * return intermediate data through hook call and construct MintReturn afterwards * return intermediate data through hook call and construct TransferFromReturn afterwards * return intermediate data through hook call and construct TransferReturn afterwards * move transfer and burn actions in the test actor into separate functions * bump frc46_token version to 0.2.0
1 parent e9371ad commit a58f063

File tree

18 files changed

+1035
-202
lines changed

18 files changed

+1035
-202
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ members = [
1515
"testing/fil_token_integration/actors/basic_receiving_actor",
1616
"testing/fil_token_integration/actors/basic_nft_actor",
1717
"testing/fil_token_integration/actors/basic_transfer_actor",
18+
"testing/fil_token_integration/actors/test_actor"
1819
]

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ test-coverage: install-toolchain
2222
--exclude basic_token_actor \
2323
--exclude basic_receiving_actor \
2424
--exclude basic_nft_actor \
25-
--exclude basic_transfer_actor
25+
--exclude basic_transfer_actor \
26+
--exclude test_actor
2627

2728
# separate actor testing stage to run from CI without coverage support
2829
test-actors: install-toolchain

frc46_token/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "frc46_token"
33
description = "Filecoin FRC-0046 fungible token reference implementation"
4-
version = "0.1.0"
4+
version = "0.2.0"
55
license = "MIT OR Apache-2.0"
66
keywords = ["filecoin", "fvm", "token", "frc-0046"]
77
repository = "https://github.com/helix-onchain/filecoin/"

frc46_token/src/token/mod.rs

Lines changed: 111 additions & 58 deletions
Large diffs are not rendered by default.

frc46_token/src/token/types.rs

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,17 @@ pub struct MintReturn {
129129
}
130130

131131
impl Cbor for MintReturn {}
132-
impl RecipientData for MintReturn {
132+
133+
/// Intermediate data used by mint_return to construct the return data
134+
#[derive(Debug)]
135+
pub struct MintIntermediate {
136+
/// Recipient address to use for querying balance
137+
pub recipient: Address,
138+
/// (Optional) data returned from receiver hook
139+
pub recipient_data: RawBytes,
140+
}
141+
142+
impl RecipientData for MintIntermediate {
133143
fn set_recipient_data(&mut self, data: RawBytes) {
134144
self.recipient_data = data;
135145
}
@@ -158,7 +168,17 @@ pub struct TransferReturn {
158168

159169
impl Cbor for TransferParams {}
160170
impl Cbor for TransferReturn {}
161-
impl RecipientData for TransferReturn {
171+
172+
/// Intermediate data used by transfer_return to construct the return data
173+
#[derive(Debug)]
174+
pub struct TransferIntermediate {
175+
pub from: Address,
176+
pub to: Address,
177+
/// (Optional) data returned from receiver hook
178+
pub recipient_data: RawBytes,
179+
}
180+
181+
impl RecipientData for TransferIntermediate {
162182
fn set_recipient_data(&mut self, data: RawBytes) {
163183
self.recipient_data = data;
164184
}
@@ -190,7 +210,18 @@ pub struct TransferFromReturn {
190210

191211
impl Cbor for TransferFromParams {}
192212
impl Cbor for TransferFromReturn {}
193-
impl RecipientData for TransferFromReturn {
213+
214+
/// Intermediate data used by transfer_from_return to construct the return data
215+
#[derive(Debug)]
216+
pub struct TransferFromIntermediate {
217+
pub operator: Address,
218+
pub from: Address,
219+
pub to: Address,
220+
/// (Optional) data returned from receiver hook
221+
pub recipient_data: RawBytes,
222+
}
223+
224+
impl RecipientData for TransferFromIntermediate {
194225
fn set_recipient_data(&mut self, data: RawBytes) {
195226
self.recipient_data = data;
196227
}

testing/fil_token_integration/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ cid = { version = "0.8.5", default-features = false }
1010
fvm = { version = "2.0.0-alpha.2", default-features = false }
1111
frcxx_nft = { path = "../../frcxx_nft" }
1212
frc42_dispatch = { path = "../../frc42_dispatch" }
13-
frc46_token = { version = "0.1.0", path = "../../frc46_token" }
13+
frc46_token = { version = "0.2.0", path = "../../frc46_token" }
1414
fvm_integration_tests = "2.0.0-alpha.1"
1515
fvm_ipld_blockstore = "0.1.1"
1616
fvm_ipld_encoding = "0.2.2"
@@ -24,3 +24,4 @@ basic_nft_actor = {path = "actors/basic_nft_actor"}
2424
basic_receiving_actor = { path = "actors/basic_receiving_actor" }
2525
basic_token_actor = { path = "actors/basic_token_actor" }
2626
basic_transfer_actor = { path = "actors/basic_transfer_actor" }
27+
test_actor = { path = "actors/test_actor" }

testing/fil_token_integration/actors/basic_receiving_actor/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7-
frc46_token = { version = "0.1.0", path = "../../../../frc46_token" }
7+
frc46_token = { version = "0.2.0", path = "../../../../frc46_token" }
88
frc42_dispatch = { path = "../../../../frc42_dispatch" }
99
fvm_ipld_blockstore = "0.1.1"
1010
fvm_ipld_encoding = "0.2.2"

testing/fil_token_integration/actors/basic_token_actor/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ repository = "https://github.com/helix-collective/filecoin"
55
edition = "2021"
66

77
[dependencies]
8+
cid = { version = "0.8.5", default-features = false }
89
fvm_actor_utils = { version = "0.1.0", path = "../../../../fvm_actor_utils" }
910
fvm_ipld_blockstore = { version = "0.1.1" }
1011
fvm_ipld_encoding = { version = "0.2.2" }
1112
fvm_sdk = { version = "2.0.0-alpha.2" }
1213
fvm_shared = { version = "2.0.0-alpha.2" }
13-
frc46_token = { version = "0.1.0", path = "../../../../frc46_token" }
14+
frc46_token = { version = "0.2.0", path = "../../../../frc46_token" }
1415
num-traits = { version = "0.2.15" }
1516
serde = { version = "1.0.136", features = ["derive"] }
1617
serde_tuple = { version = "0.5.0" }

testing/fil_token_integration/actors/basic_token_actor/src/lib.rs

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod util;
22

3+
use cid::Cid;
34
use frc46_token::token::types::{
45
AllowanceReturn, BalanceReturn, BurnFromReturn, BurnParams, BurnReturn,
56
DecreaseAllowanceParams, FRC46Token, GetAllowanceParams, GranularityReturn,
@@ -63,7 +64,10 @@ impl FRC46Token<RuntimeError> for BasicToken<'_> {
6364
let cid = self.util.flush()?;
6465
sdk::sself::set_root(&cid).unwrap();
6566

66-
let ret = hook.call(self.util.msg())?;
67+
let hook_ret = hook.call(self.util.msg())?;
68+
69+
self.reload(&cid)?;
70+
let ret = self.util.transfer_return(hook_ret)?;
6771

6872
Ok(ret)
6973
}
@@ -85,7 +89,10 @@ impl FRC46Token<RuntimeError> for BasicToken<'_> {
8589
let cid = self.util.flush()?;
8690
sdk::sself::set_root(&cid).unwrap();
8791

88-
let ret = hook.call(self.util.msg())?;
92+
let hook_ret = hook.call(self.util.msg())?;
93+
94+
self.reload(&cid)?;
95+
let ret = self.util.transfer_from_return(hook_ret)?;
8996

9097
Ok(ret)
9198
}
@@ -141,24 +148,37 @@ impl FRC46Token<RuntimeError> for BasicToken<'_> {
141148
pub struct MintParams {
142149
pub initial_owner: Address,
143150
pub amount: TokenAmount,
151+
pub operator_data: RawBytes,
144152
}
145153

146154
impl Cbor for MintParams {}
147155

148156
impl BasicToken<'_> {
157+
fn reload(&mut self, initial_cid: &Cid) -> Result<(), RuntimeError> {
158+
// todo: revise error type here so it plays nice with the result and doesn't need unwrap
159+
let new_cid = sdk::sself::root().unwrap();
160+
if new_cid != *initial_cid {
161+
self.util.load_replace(&new_cid)?;
162+
}
163+
Ok(())
164+
}
165+
149166
fn mint(&mut self, params: MintParams) -> Result<MintReturn, RuntimeError> {
150167
let mut hook = self.util.mint(
151168
&caller_address(),
152169
&params.initial_owner,
153170
&params.amount,
154-
Default::default(),
171+
params.operator_data,
155172
Default::default(),
156173
)?;
157174

158175
let cid = self.util.flush()?;
159176
sdk::sself::set_root(&cid).unwrap();
160177

161-
let ret = hook.call(self.util.msg())?;
178+
let hook_ret = hook.call(self.util.msg())?;
179+
180+
self.reload(&cid)?;
181+
let ret = self.util.mint_return(hook_ret)?;
162182

163183
Ok(ret)
164184
}
@@ -269,28 +289,21 @@ pub fn invoke(params: u32) -> u32 {
269289
// TransferFrom
270290
let params = deserialize_params(params);
271291
let res = token_actor.transfer_from(params).unwrap();
272-
let cid = token_actor.util.flush().unwrap();
273-
sdk::sself::set_root(&cid).unwrap();
274292
return_ipld(&res).unwrap()
275293
}
276294
1303003700 => {
277295
// Transfer
278296
let params = deserialize_params(params);
279297
let res = token_actor.transfer(params).unwrap();
280-
let cid = token_actor.util.flush().unwrap();
281-
sdk::sself::set_root(&cid).unwrap();
282298
return_ipld(&res).unwrap()
283299
}
284300

285301
// Custom actor interface, these are author-defined methods that extend beyond the
286302
// FRC46 Token standard
287303
3839021839 => {
288304
// Mint
289-
let params = deserialize_params(params);
305+
let params: MintParams = deserialize_params(params);
290306
let res = token_actor.mint(params).unwrap();
291-
292-
let cid = token_actor.util.flush().unwrap();
293-
sdk::sself::set_root(&cid).unwrap();
294307
return_ipld(&res).unwrap()
295308
}
296309
_ => {

testing/fil_token_integration/actors/basic_transfer_actor/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
cid = { version = "0.8.5", default-features = false }
8-
frc46_token = { version = "0.1.0", path = "../../../../frc46_token" }
8+
frc46_token = { version = "0.2.0", path = "../../../../frc46_token" }
99
frc42_dispatch = { path = "../../../../frc42_dispatch" }
1010
fvm_ipld_blockstore = { version = "0.1.1" }
1111
fvm_ipld_encoding = { version = "0.2.2" }

0 commit comments

Comments
 (0)