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

Minimal Vault, Router, Transient Accounting #81

Merged
merged 84 commits into from
Sep 19, 2023
Merged

Conversation

ylv-io
Copy link
Contributor

@ylv-io ylv-io commented Aug 6, 2023

Description

This PR introduces a new design comprised of three contracts: Router<>Vault<>Pool. This design parallels the previous Relayer<>Vault<>Pool structure. The key distinction lies in the Vault API, which is more internally driven than user-centric. Another design feature is transitional accounting. This approach enables multiple operations within a transaction, settling token balances only at the conclusion. It also permits arbitrary calls to other contracts amidst vault operations, thereby facilitating use-cases such as 'addLiquidity' followed by 'stake'.

The benefits of this model include:

  • A streamlined Vault that is simpler to develop, test, and audit. By relocating the complexity of numerous operations to the Router, potential Vault issues are minimized. This is crucial since redeploying the Vault isn't straightforward.
  • By having the Router/Relayer shoulder the Vault's complexity, we can introduce numerous external functions without the Vault's bytecode size limitation. Additionally, multiple Routers can exist, though one should suffice.
  • Direct support for flash loans without additional coding.
  • Facilitation of internal balances without extra coding, offering an ERC20-like API for internal balance management.
  • Capability to determine user balances across various operations such as adding/removing liquidity or swaps.

The Vault API offers functions like settle, wire, mint, retrieve, and burn to finalize balances. These functions ensure token transfers occur at a transaction's end, settling any outstanding balances. Concurrently, they enable flash loans; for instance, one can mint a specific quantity of token A and exchange it. This token A amount would only require repayment at the transaction's conclusion.

The Vault's security is of utmost importance. Therefore, the integrity of its logic is non-negotiable. The transient modifier serves this purpose. It's a potent code ensuring two end-of-transaction invariants: a) all accounts are settled to zero; if not, a BalanceNotSettled alert is triggered and all modifications are reverted, and b) it confirms we are the final handler.

    modifier transient() {
        _handlers.push(msg.sender);

        // the caller does everything here, and has to settle all outstanding balances
        _;

        if (_handlers.length == 1) {
            if (_nonzeroDeltaCount != 0) revert BalanceNotSettled();
            delete _handlers;
            delete _nonzeroDeltaCount;
        } else {
            _handlers.pop();
        }
    }

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Dependency changes
  • Code refactor / cleanup
  • Documentation or wording changes
  • Other

Checklist:

  • The diff is legible and has no extraneous changes
  • Complex code has been commented, including external interfaces
  • Tests have 100% code coverage
  • The base branch is either main, or there's a description of how to merge

Issue Resolution

Closes #39.
Closes #40.
Closes #41.

@jubeira
Copy link
Contributor

jubeira commented Aug 31, 2023

Would it help to start merging this to keep the house clean?

We can always go back and / or iterate over it. @ylv-io @danielmkm @EndymionJkb WDYT?

Copy link
Contributor

@jubeira jubeira left a comment

Choose a reason for hiding this comment

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

Just two more open questions so as not to lose sight of the original problem in V2, and triple check.

pkg/vault/contracts/Router.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Router.sol Outdated Show resolved Hide resolved
Copy link
Contributor

@jubeira jubeira left a comment

Choose a reason for hiding this comment

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

I've done one more pass while wrapping my head around trying to figure out how to best document this.

I've picked up mostly nits and silly questions, and just a few important comments :)

And I have to say that I come back to this and I'm yet again impressed by the design; great job!

pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
Copy link
Collaborator

@EndymionJkb EndymionJkb left a comment

Choose a reason for hiding this comment

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

Forgot to submit...

pkg/interfaces/contracts/vault/IBasePool.sol Show resolved Hide resolved
pkg/interfaces/contracts/vault/IBasePool.sol Show resolved Hide resolved
pkg/interfaces/contracts/vault/IBasePool.sol Show resolved Hide resolved
pkg/interfaces/contracts/vault/IRouter.sol Show resolved Hide resolved
pkg/interfaces/contracts/vault/IVault.sol Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
pkg/vault/contracts/Vault.sol Outdated Show resolved Hide resolved
Copy link
Contributor

@jubeira jubeira left a comment

Choose a reason for hiding this comment

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

🚀 let's gooo!
I think this is good to go. I'd suggest merging, @EndymionJkb @danielmkm please feel free to take a look after the PR is closed if you want to, but I think it's a good time to move forward.

@ylv-io
Copy link
Contributor Author

ylv-io commented Sep 13, 2023

Handlers are Routers, right? Could we just say router? That would be consistent, and we wouldn't have to introduce a new term (if it's true that handlers are always routers.)

Handlers, were a temp name. I like Routers, what do you think @jubeira ?

@ylv-io
Copy link
Contributor Author

ylv-io commented Sep 13, 2023

My intuition is you want to enforce limits as part of the settlement, so it should be in the Vault. The general pattern would be:
validate inputs (i.e., tokens are valid for this pool)
do the thing
check invariants / post-conditions (e.g., all routers completed, zero deltas, deadline and limits met)
Especially because you can have random other routers, which might "forget" to validate things. Transactions could then successfully settle with violated limits.

But min amounts out are not invariants and do not affect Vault security. It is true that they may result to users losing money on horrible trades. If we want to keep Vault minimal it seems okay to put this in the Router.

Copy link
Contributor

@danielmkm danielmkm left a comment

Choose a reason for hiding this comment

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

Added some comments, but agree that we should get this merged. It's hard to get a full sense of the current state based on this PR alone anymore.

…ountsIn instead of maxAmountsIn and update the return variable names. Also, remove the check for minBptAmountOut in Router.sol.
…nction in Vault.sol for better readability and maintainability.
@ylv-io ylv-io merged commit 7763ad1 into main Sep 19, 2023
7 checks passed
@jubeira jubeira deleted the transient-accounting branch September 19, 2023 12:18
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.

Implement swap Implement exit Implement join
4 participants