Skip to content

Commit 950d95d

Browse files
committed
integration test
1 parent 9383f3a commit 950d95d

File tree

10 files changed

+198
-49
lines changed

10 files changed

+198
-49
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@ members = [
44
"fvm_dispatch",
55
"fil_token",
66
"testing/integration",
7-
"testing/integration/actors/fil_token_actor",
7+
"testing/integration/actors/wfil_token_actor",
88
]

fil_token/src/runtime/fvm.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
use super::Runtime;
2+
3+
use anyhow::{anyhow, Result};
4+
use fvm_sdk as sdk;
5+
use sdk::actor;
6+
use sdk::message;
7+
8+
pub struct FvmRuntime {}
9+
10+
impl Runtime for FvmRuntime {
11+
fn caller(&self) -> u64 {
12+
message::caller()
13+
}
14+
15+
fn resolve_address(&self, addr: &fvm_shared::address::Address) -> Result<u64> {
16+
actor::resolve_address(addr).ok_or_else(|| anyhow!("Failed to resolve address"))
17+
}
18+
}

fil_token/src/runtime/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
mod fvm;
2+
pub use fvm::*;
3+
14
use anyhow::Result;
25
use fvm_shared::address::Address;
36

fil_token/src/token/mod.rs

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ macro_rules! abort {
2828

2929
/// A standard fungible token interface allowing for on-chain transactions
3030
pub trait Token {
31-
/// Constructs the token
32-
fn constructor(&self, params: ConstructorParams) -> Result<()>;
33-
3431
/// Returns the name of the token
3532
fn name(&self) -> String;
3633

@@ -86,8 +83,15 @@ where
8683
BS: IpldStore + Copy,
8784
FVM: Runtime,
8885
{
89-
fn load_state(&self) -> TokenState {
90-
TokenState::load(&self.bs)
86+
pub fn new(bs: BS, fvm: FVM) -> Self {
87+
Self { bs, fvm }
88+
}
89+
90+
/// Constructs the token
91+
pub fn init_state(&self, params: ConstructorParams) -> Result<()> {
92+
let init_state = TokenState::new(&self.bs, &params.name, &params.symbol)?;
93+
init_state.save(&self.bs);
94+
Ok(())
9195
}
9296

9397
// Utility function for token-authors to mint supply
@@ -99,26 +103,15 @@ where
99103
let mut state = self.load_state();
100104
let mut balances = state.get_balance_map(&self.bs);
101105

102-
let holder = match self.fvm.resolve_address(&params.initial_holder) {
103-
Ok(id) => id,
104-
Err(_) => {
105-
return Ok(MintReturn {
106-
newly_minted: TokenAmount::zero(),
107-
successful: false,
108-
total_supply: state.supply,
109-
})
110-
}
111-
};
112-
113106
// Mint the tokens into a specified account
114107
let balance = balances
115-
.delete(&holder)?
108+
.delete(&params.initial_holder)?
116109
.map(|de| de.1 .0)
117110
.unwrap_or_else(TokenAmount::zero);
118111
let new_balance = balance
119112
.checked_add(&params.value)
120113
.ok_or_else(|| ActorError::Arithmetic(String::from("Minting into caused overflow")))?;
121-
balances.set(holder, BigIntDe(new_balance))?;
114+
balances.set(params.initial_holder, BigIntDe(new_balance))?;
122115

123116
// set the global supply of the contract
124117
let new_supply = state.supply.checked_add(&params.value).ok_or_else(|| {
@@ -135,19 +128,18 @@ where
135128
total_supply: state.supply,
136129
})
137130
}
131+
132+
/// Helper function that loads the root of the state tree related to token-accounting
133+
fn load_state(&self) -> TokenState {
134+
TokenState::load(&self.bs)
135+
}
138136
}
139137

140138
impl<BS, FVM> Token for TokenHelper<BS, FVM>
141139
where
142140
BS: IpldStore + Copy,
143141
FVM: Runtime,
144142
{
145-
fn constructor(&self, params: ConstructorParams) -> Result<()> {
146-
let init_state = TokenState::new(&self.bs, &params.name, &params.symbol)?;
147-
init_state.save(&self.bs);
148-
Ok(())
149-
}
150-
151143
fn name(&self) -> String {
152144
let state = self.load_state();
153145
state.name

fil_token/src/token/types.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use fvm_ipld_encoding::{Cbor, RawBytes};
33
use fvm_shared::address::Address;
44
use fvm_shared::bigint::bigint_ser;
55
use fvm_shared::econ::TokenAmount;
6+
use fvm_shared::ActorID;
67

78
#[derive(Serialize_tuple, Deserialize_tuple)]
89
pub struct ConstructorParams {
@@ -14,7 +15,7 @@ pub struct ConstructorParams {
1415
/// Called during construction of the token actor to set a supply
1516
#[derive(Serialize_tuple, Deserialize_tuple)]
1617
pub struct MintParams {
17-
pub initial_holder: Address,
18+
pub initial_holder: ActorID,
1819
#[serde(with = "bigint_ser")]
1920
pub value: TokenAmount,
2021
}

testing/integration/actors/fil_token_actor/src/lib.rs

Lines changed: 0 additions & 22 deletions
This file was deleted.

testing/integration/actors/fil_token_actor/Cargo.toml renamed to testing/integration/actors/wfil_token_actor/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
[package]
2-
name = "fil_token_actor"
2+
name = "wfil_token_actor"
33
version = "0.1.0"
44
repository = "https://github.com/helix-collective/filecoin"
55
edition = "2021"
66

77
[dependencies]
8+
anyhow = { version = "1.0.56" }
9+
fvm_ipld_encoding = { version = "0.2.2" }
810
fvm_sdk = { version = "1.0.0 "}
911
fvm_shared = { version = "0.8.0" }
1012
fil_token = { version = "0.1.0", path = "../../../../fil_token" }
File renamed without changes.
File renamed without changes.
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use anyhow::Result;
2+
use fil_token::blockstore::Blockstore;
3+
use fil_token::runtime::FvmRuntime;
4+
use fil_token::token::types::*;
5+
use fil_token::token::{Token, TokenHelper};
6+
use fvm_ipld_encoding::{RawBytes, DAG_CBOR};
7+
use fvm_sdk as sdk;
8+
use fvm_shared::bigint::bigint_ser::BigIntSer;
9+
use fvm_shared::econ::TokenAmount;
10+
use sdk::NO_DATA_BLOCK_ID;
11+
12+
struct WfilToken {
13+
/// Default token helper impl
14+
util: TokenHelper<Blockstore, FvmRuntime>,
15+
}
16+
17+
// TODO: Wrapper is unecessary?
18+
// Instead expose a
19+
impl Token for WfilToken {
20+
fn name(&self) -> String {
21+
String::from("Wrapped FIL")
22+
}
23+
24+
fn symbol(&self) -> String {
25+
String::from("WFIL")
26+
}
27+
28+
fn total_supply(&self) -> TokenAmount {
29+
self.util.total_supply()
30+
}
31+
32+
fn balance_of(
33+
&self,
34+
params: fvm_shared::address::Address,
35+
) -> Result<fvm_shared::econ::TokenAmount> {
36+
self.util.balance_of(params)
37+
}
38+
39+
fn increase_allowance(&self, params: ChangeAllowanceParams) -> Result<AllowanceReturn> {
40+
self.util.increase_allowance(params)
41+
}
42+
43+
fn decrease_allowance(&self, params: ChangeAllowanceParams) -> Result<AllowanceReturn> {
44+
self.util.decrease_allowance(params)
45+
}
46+
47+
fn revoke_allowance(&self, params: RevokeAllowanceParams) -> Result<AllowanceReturn> {
48+
self.util.revoke_allowance(params)
49+
}
50+
51+
fn allowance(&self, params: GetAllowanceParams) -> Result<AllowanceReturn> {
52+
self.util.allowance(params)
53+
}
54+
55+
fn burn(&self, params: BurnParams) -> Result<BurnReturn> {
56+
self.util.burn(params)
57+
}
58+
59+
fn transfer_from(&self, params: TransferParams) -> Result<TransferReturn> {
60+
self.util.transfer_from(params)
61+
}
62+
}
63+
64+
/// Placeholder invoke for testing
65+
#[no_mangle]
66+
pub fn invoke(params: u32) -> u32 {
67+
// Conduct method dispatch. Handle input parameters and return data.
68+
let method_num = sdk::message::method_number();
69+
70+
let token_actor = WfilToken {
71+
util: TokenHelper::new(Blockstore {}, FvmRuntime {}),
72+
};
73+
74+
//TODO: this internal dispatch can be pushed as a library function into the fil_token crate
75+
// - it should support a few different calling-conventions
76+
// - it should also handle deserialization of raw_params into the expected IPLD types
77+
let res = match method_num {
78+
// Actor constructor
79+
1 => constructor(),
80+
// Standard token interface
81+
2 => {
82+
token_actor.name();
83+
// TODO: store and return CID
84+
NO_DATA_BLOCK_ID
85+
}
86+
3 => {
87+
token_actor.symbol();
88+
// TODO: store and return CID
89+
NO_DATA_BLOCK_ID
90+
}
91+
4 => {
92+
token_actor.total_supply();
93+
// TODO: store and return CID
94+
NO_DATA_BLOCK_ID
95+
}
96+
5 => {
97+
// balance of
98+
let params = sdk::message::params_raw(params).unwrap().1;
99+
let params = RawBytes::new(params);
100+
let params = params.deserialize().unwrap();
101+
let res = token_actor.balance_of(params).unwrap();
102+
let res = RawBytes::new(fvm_ipld_encoding::to_vec(&BigIntSer(&res)).unwrap());
103+
let cid = sdk::ipld::put_block(DAG_CBOR, res.bytes()).unwrap();
104+
cid
105+
}
106+
6 => {
107+
// increase allowance
108+
NO_DATA_BLOCK_ID
109+
}
110+
7 => {
111+
// decrease allowance
112+
NO_DATA_BLOCK_ID
113+
}
114+
8 => {
115+
// revoke_allowance
116+
NO_DATA_BLOCK_ID
117+
}
118+
9 => {
119+
// allowance
120+
NO_DATA_BLOCK_ID
121+
}
122+
10 => {
123+
// burn
124+
NO_DATA_BLOCK_ID
125+
}
126+
11 => {
127+
// transfer_from
128+
NO_DATA_BLOCK_ID
129+
}
130+
// Custom actor interface
131+
12 => {
132+
// Mint
133+
let params = MintParams {
134+
initial_holder: sdk::message::caller(),
135+
value: sdk::message::value_received(),
136+
};
137+
let res = token_actor.util.mint(params).unwrap();
138+
let res = RawBytes::new(fvm_ipld_encoding::to_vec(&res).unwrap());
139+
let cid = sdk::ipld::put_block(DAG_CBOR, res.bytes()).unwrap();
140+
cid
141+
}
142+
_ => {
143+
sdk::vm::abort(
144+
fvm_shared::error::ExitCode::USR_ILLEGAL_ARGUMENT.value(),
145+
Some("Unknown method number"),
146+
);
147+
}
148+
};
149+
150+
res
151+
}
152+
153+
fn constructor() -> u32 {
154+
0_u32
155+
}

0 commit comments

Comments
 (0)