Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

token-swap: Add instructions to deposit / withdraw one token #937

Merged
merged 9 commits into from
Dec 16, 2020

Conversation

joncinque
Copy link
Contributor

@joncinque joncinque commented Dec 9, 2020

In order to properly support the new curves, we need the ability to deposit or withdraw just one side of the token swap. This uses the interface added in #934.

Since the math part is covered in other PRs, this focuses on the interface into processor.rs, and the tests closely mirror the logic to test the normal withdraw and deposit instructions.

@joncinque joncinque changed the title WIP token-swap: Add instructions to deposit / withdraw one token token-swap: Add instructions to deposit / withdraw one token Dec 10, 2020
@joncinque joncinque marked this pull request as ready for review December 10, 2020 19:17
Copy link
Contributor Author

@joncinque joncinque left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the tests in processor.rs mimic the checks from withdraw and deposit, so there may be some other cases to check

@@ -110,8 +110,14 @@ impl SwapCurve {
trade_direction: TradeDirection,
fees: &Fees,
) -> Option<u128> {
// Get the trading fee incurred if the owner fee is swapped for the other side
let trade_fee = fees.trading_fee(source_amount)?;
// Get the trading fee incurred if *half* the source amount is swapped
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also done in #936

@@ -68,6 +68,30 @@ pub struct Withdraw {
pub minimum_token_b_amount: u64,
}

/// Deposit one exact in instruction data
#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fuzzing will come later

@@ -143,6 +146,58 @@ impl Processor {
)
}

#[allow(clippy::too_many_arguments)]
fn check_accounts(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This felt like a nice refactor :-)

),
};

let burn_pool_token_amount = token_swap
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To do exact amount out, we have to calculate the amount and then tack the fee on afterward

@joncinque
Copy link
Contributor Author

CI passes locally

Copy link
Contributor

@CriesofCarrots CriesofCarrots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on my understanding of the math, this looks functionally good. Wouldn't hurt to get another pair of eyes on it, though.
I think the names for the new instructions could perhaps be more clear/precise. Wdyt?

@@ -127,6 +151,33 @@ pub enum SwapInstruction {
/// 8. `[writable]` Fee account, to receive withdrawal fees
/// 9. '[]` Token program id
Withdraw(Withdraw),

/// Deposit some tokens into the pool. The output is a "pool" token
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on this comment, I don't see any difference between Deposit and DepositOneExactIn. Can you make it more descriptive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a good point, I didn't want to change the name of the previous instructions, but it definitely makes things clearer. We could change Withdraw / Deposit to WithdrawAll / DepositAll -- what do you think?

/// 5. `[writable]` Pool MINT account, $authority is the owner.
/// 6. `[writable]` Pool Account to deposit the generated tokens, user is the owner.
/// 7. '[]` Token program id
DepositOneExactIn(DepositOneExactIn),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I'm not crazy about DepositOneExactIn. "One" makes me think I'm depositing amount one, I'm not sure what is "exact", and "in" seems redundant. ...Is there precedent for this nomenclature elsewhere in swap-land? If not... what about DepositAndSwap?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean... I wanted to make it clear that you're only depositing one token type instead of both, and that you're specifying exactly how much is going in, as opposed to the old deposit, which specifies the exact amount of pool tokens that you'll get out. Since it's not actually performing a swap, DepositAndSwap seems misleading. What about DepositOneSideExactAmountIn to be totally clear?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you expect to also support depositing one side but specifying the input in pool tokens? If not, I don't think ExactAmountIn is needed. That can just be defined in the interface.
Are we still looking toward pools of >2 tokens?
How about DepositSingleTokenType

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful for people to be able to specify which side they want to fix when depositing or withdrawing, and it's something used in Balancer, so providing that info in this instruction would be best. DepositSingleTokenType definitely clarifies the One part -- what about DepositSingleTokenTypeExactAmountIn? For reference, I was looking at Balancer's terminology at https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol -- but I found functions like joinswapExternAmountIn opaque, so I'm very motivated to make this clear for us!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So hard to find something both precise and concise! ;)
DepositSingleTokenTypeExactAmountIn is at least very clear... wfm

@@ -676,6 +706,272 @@ impl Processor {
Ok(())
}

/// Processes DepositOneExactIn
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Processes DepositOneExactIn
/// Processes [DepositOneExactIn](enum.Instruction.html)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wondering -- what does this do?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are just markdown links for when the docs are published to docs.rs, eg: https://docs.rs/spl-token/3.0.0/spl_token/processor/struct.Processor.html
But it looks like we're not composing those quite right in spl-token; they need to go to ../instruction/enum.TokenInstruction.html 😳. And here, they also need to be renamed to SwapInstruction. Feel free to ignore for the time being, but let's get these updated before we publish a v1 to crates.io

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use the simpler markdown as in https://doc.rust-lang.org/rustdoc/linking-to-items-by-name.html? I'm surprised this didn't get caught by the lints. Definitely something else to look into

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh cool, it looks like it; that's way better. I haven't dug into rustdoc as I should

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only looked into it just now 😆

Ok(())
}

/// Processes an [Withdraw](enum.Instruction.html).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/// Processes an [Withdraw](enum.Instruction.html).
/// Processes an [WithdrawOneExactOut](enum.Instruction.html).

/// 6. `[writable]` token_(A|B) User Account to credit
/// 7. `[writable]` Fee account, to receive withdrawal fees
/// 8. '[]` Token program id
WithdrawOneExactOut(WithdrawOneExactOut),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto with this instruction name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WithdrawOneSideExactAmountOut for this?

@joncinque
Copy link
Contributor Author

This should be good to go with the renames now!

Copy link
Contributor

@CriesofCarrots CriesofCarrots left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Much better. Thanks for the comment expansion as well!

@joncinque joncinque merged commit 7190672 into solana-labs:master Dec 16, 2020
@joncinque joncinque deleted the ts-insts branch December 21, 2020 16:29
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants