Skip to content
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

EIP-4626 Withdrawals with a crank #46

Merged
merged 19 commits into from
Oct 18, 2022
Merged

EIP-4626 Withdrawals with a crank #46

merged 19 commits into from
Oct 18, 2022

Conversation

venables
Copy link
Contributor

@venables venables commented Oct 7, 2022

  • Allow lenders to request to redeem (ask for # of shares to convert), or withdraw (ask for an amount of $$)
  • Adds support for all EIP-4626 withdraw/redeem methods, as well as the equivalent for withdrawRequest/redeemRequest
  • Adds a "light" crank to allocate balances to the right people. This actually takes up about the same amount of gas as the "heavy" crank, but allows for 4626 support.
  • Cleaned up the method logic and naming
  • Moved most logic to the PoolLib
  • Charge a fee when making a withdraw / redeem request

@venables venables changed the title EIP-4626 style requests EIP-4626 Withdrawals with a crank Oct 14, 2022
@@ -114,6 +125,13 @@ contract Pool is IPool, ERC20 {
_serviceConfiguration = IServiceConfiguration(serviceConfiguration);
_firstLossVault = new FirstLossVault(address(this), liquidityAsset);
_setPoolLifeCycleState(IPoolLifeCycleState.Initialized);

// Allow the contract to move infinite amount of vault liquidity assets
bool approved = _liquidityAsset.approve(
Copy link
Contributor

Choose a reason for hiding this comment

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

We need this because we use transferFrom for moving the funds during actual withdrawal right? What's the advantage over using safeTransfer there instead and omitting this?

Copy link
Contributor Author

@venables venables Oct 18, 2022

Choose a reason for hiding this comment

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

I believe we would still need the approve here regardless if using safeTrasnferFrom or not, but I will double check.

* is set to 10_000 (100%)
*/
function withdrawGate() public view returns (uint256) {
if (_poolLifeCycleState == IPoolLifeCycleState.Closed) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice. Do you think we also need to check ... || now < poolCloseTime?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Great call -- I've update this to use the method lifeCycleState() which will consider the pool endDate as well. We may need to consider this same change for the modifiers as well.

function crank() external returns (uint256 redeemableShares) {
// Calculate the amount available for withdrawal
// TODO: Find the real available liquidity
uint256 availableLiquidity = totalSupply();
Copy link
Contributor

@ams9198 ams9198 Oct 17, 2022

Choose a reason for hiding this comment

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

Would this just be USDC.balanceOf(this), i.e. liquidity reserve?

Edit: to avoid overdrafting the liquidity reserve, I wonder if we instead start with the liquidity reserve, calculate the withdrawal-gate portion, and then convert that to a # of shares?

@@ -507,6 +791,9 @@ contract Pool is IPool, ERC20 {
maxDeposit(receiver),
_mint
);

// Approve the contract for infinite tokens.
approve(address(this), type(uint128).max);
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there somewhere else we could put this? Does it need to be called repeatedly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, now that it's in the constructor, I've removed this.

onlyLender
returns (uint256 shares)
{
shares = convertToShares(assets);
Copy link
Contributor

Choose a reason for hiding this comment

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

Just so I understand...if you request in assets, we convert that to shares (at an exchange rate at request time), and then store the shares in the various withdrawal states?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As of now, yes, that's how it works. We store all in requests in shares. We could pretty easily store both separately but it seemed to add a bit of complexity. I don't feel strongly overall, thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool, just confirming I understood! I think we roll with this for now, and keep that in mind as we / if we tweak?


_globalWithdrawState = PoolLib.updateWithdrawStateForWithdraw(
globalState,
convertToAssets(redeemableShares),
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to exclude these earmarked shares / assets from our exchange rate calculations, e.g. convertToShares? In future work, should the assets be moved elsewhere or locked so that they'll remain available for withdrawal?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah we will have to exclude these -- treating them as essentially withdrawn. I've filed a ticket here that I can use to follow up https://circlepay.atlassian.net/browse/VAL-54

@venables venables merged commit 64dd99d into circlefin:master Oct 18, 2022
@venables venables deleted the matt/eip4626-style-requests branch October 18, 2022 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants