-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update the token-actor interface #75
Conversation
2d170f8
to
712da5f
Compare
712da5f
to
e3f0cbf
Compare
self.util.transfer(&spender, &spender, ¶ms.to, ¶ms.amount, ¶ms.data)?; | ||
|
||
// FIXME: populate with real values | ||
Ok(TransferReturn { from_balance: TokenAmount::zero(), to_balance: TokenAmount::zero() }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be more efficient if Token::transfer returned the relevant info, else we can make separate calls to Token::balance_of
and Token::allowance
etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Simple but maybe error-prone would be to return an anonymous tuple. Another alternative is to return the Return types defined earlier, but that inverts the expected dependency hierarchy. Another option is separate return structs, but they'll be a bit duplicative.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great improvement, thanks.
self.util.transfer(&spender, &spender, ¶ms.to, ¶ms.amount, ¶ms.data)?; | ||
|
||
// FIXME: populate with real values | ||
Ok(TransferReturn { from_balance: TokenAmount::zero(), to_balance: TokenAmount::zero() }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. Simple but maybe error-prone would be to return an anonymous tuple. Another alternative is to return the Return types defined earlier, but that inverts the expected dependency hierarchy. Another option is separate return structs, but they'll be a bit duplicative.
b054216
to
9bc01b1
Compare
9452fe6
to
d8a8129
Compare
d8a8129
to
a1e2175
Compare
fil_fungible_token/src/token/mod.rs
Outdated
#[derive(Debug)] | ||
pub enum TransferResult { | ||
Transfer(TransferReturn), | ||
TransferFrom(TransferFromReturn), | ||
} | ||
|
||
impl TryFrom<TransferResult> for TransferFromReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: TransferResult) -> Result<TransferFromReturn> { | ||
match value { | ||
TransferResult::TransferFrom(ret) => Ok(ret), | ||
TransferResult::Transfer(_) => Err(TokenError::TransferReturn { result: value }), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<TransferResult> for TransferReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: TransferResult) -> Result<TransferReturn> { | ||
match value { | ||
TransferResult::TransferFrom(_) => Err(TokenError::TransferReturn { result: value }), | ||
TransferResult::Transfer(ret) => Ok(ret), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum BurnResult { | ||
Burn(BurnReturn), | ||
BurnFrom(BurnFromReturn), | ||
} | ||
|
||
impl TryFrom<BurnResult> for BurnReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: BurnResult) -> Result<Self> { | ||
match value { | ||
BurnResult::Burn(ret) => Ok(ret), | ||
BurnResult::BurnFrom(_) => Err(TokenError::BurnReturn { result: value }), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<BurnResult> for BurnFromReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: BurnResult) -> Result<Self> { | ||
match value { | ||
BurnResult::BurnFrom(ret) => Ok(ret), | ||
BurnResult::Burn(_) => Err(TokenError::BurnReturn { result: value }), | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative to this might be to have separate library level methods for transfer
and transfer_from
which return different types that match the FRC interface
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This enum technique seems like it's trying too hard, and the Err cases are weird. If we're going to have this much code anyway, I think the naive duplication might be better.
72b6095
to
eaece7e
Compare
fil_fungible_token/src/token/mod.rs
Outdated
#[derive(Debug)] | ||
pub enum TransferResult { | ||
Transfer(TransferReturn), | ||
TransferFrom(TransferFromReturn), | ||
} | ||
|
||
impl TryFrom<TransferResult> for TransferFromReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: TransferResult) -> Result<TransferFromReturn> { | ||
match value { | ||
TransferResult::TransferFrom(ret) => Ok(ret), | ||
TransferResult::Transfer(_) => Err(TokenError::TransferReturn { result: value }), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<TransferResult> for TransferReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: TransferResult) -> Result<TransferReturn> { | ||
match value { | ||
TransferResult::TransferFrom(_) => Err(TokenError::TransferReturn { result: value }), | ||
TransferResult::Transfer(ret) => Ok(ret), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug)] | ||
pub enum BurnResult { | ||
Burn(BurnReturn), | ||
BurnFrom(BurnFromReturn), | ||
} | ||
|
||
impl TryFrom<BurnResult> for BurnReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: BurnResult) -> Result<Self> { | ||
match value { | ||
BurnResult::Burn(ret) => Ok(ret), | ||
BurnResult::BurnFrom(_) => Err(TokenError::BurnReturn { result: value }), | ||
} | ||
} | ||
} | ||
|
||
impl TryFrom<BurnResult> for BurnFromReturn { | ||
type Error = TokenError; | ||
|
||
fn try_from(value: BurnResult) -> Result<Self> { | ||
match value { | ||
BurnResult::BurnFrom(ret) => Ok(ret), | ||
BurnResult::Burn(_) => Err(TokenError::BurnReturn { result: value }), | ||
} | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This enum technique seems like it's trying too hard, and the Err cases are weird. If we're going to have this much code anyway, I think the naive duplication might be better.
@@ -18,172 +18,205 @@ pub enum ActorError<Err> { | |||
pub type Result<T, E> = std::result::Result<T, ActorError<E>>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be tricky for users to implement, primarily because of the ActorError
type defined here. E.g. the builtin actors already return a Result<T, ActorError>
but my ActorError is a different type than this. Can this trait be fully generic over the result's error type?
Also, we don't strictly need this trait. It's helpful to ensure full implementation, but I've done fine without it. If we can't get it to be universally helpful to users, we could drop it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll do some thinking and experimenting around this but deferred for a followup
* update the public token-actor interface * update example actor to match new interface * check receiver hooks * cleanup naming * align with FRC-0046 * fix CI build * exclude wasm actors from code coverage * rearrange params * use RawBytes rather than Default * split burn/burn_from transfer/transfer_from
* add integration test contract * write example basic token actor * wip * add build script for example actor * update example actor to latest token api * lock fvm version for example actor test also disables default features because we don't need GPU support (or the dependencies that brings) for running tests * add fil_integration_tests to Makefile * pretty-print the message results in token actor test * use a helper function to simplify messaging in tests * add a barebones actor to implement a receiver hook * extend the mint implementation and mint tokens to the receiver actor * Update the token-actor interface (#75) * update the public token-actor interface * update example actor to match new interface * check receiver hooks * cleanup naming * align with FRC-0046 * fix CI build * exclude wasm actors from code coverage * rearrange params * use RawBytes rather than Default * split burn/burn_from transfer/transfer_from * Split receiver hook calls from minting and transfer - part 1 (#76) * wip: split minting and receiver hook calling, save state at actor level * simplify call_receiver_hook * don't try to reset state on minting failure, let invoke deal with it * set a panic hook to use the vm::abort like built-in actors do this means we'll get back meaningful errors if an unwrap() explodes * token code cleanup * gracefully handle empty return data on minting failure in mint_tokens test * further cleanup * use a more appropriate error code for "unknown method" abort * split receiver hook call out of transfer and transfer_from * remove call_receiver_hook_or_revert * ignore failing mint/transfer tests They're expecting the old behaviour of reverting state (instead of aborting) when a mint or transfer (or receiver hook) fails. Once there's a new method of calling the receiver hook (through a type returned by mint or transfer calls) they can either be adapted to that or rewritten as integration tests * update dispatch crate name * code cleanup * set_root after flushing state in method calls, so the state tree is kept up to date Co-authored-by: Andrew Bright <abright@users.noreply.github.com>
filecoin-project/FIPs#407 should be sync'd with the new interface/types defined here