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

Arrakis Modular Architecture #14

Open
Gevarist opened this issue Dec 4, 2023 · 0 comments
Open

Arrakis Modular Architecture #14

Gevarist opened this issue Dec 4, 2023 · 0 comments

Comments

@Gevarist
Copy link
Contributor

Gevarist commented Dec 4, 2023

Introduction

Arrakis Modular is intend to be an evolution of Arrakis V2, Arrakis Modular will be a modular version of Arrakis V2 where we will be able to use multiple type of dexes and protocols. Easier integration of new protocols is the main feature of Arrakis Modular.

Here a diagram of the new Arrakis Modular architecture.

Arrakis Modular New Architecture

The goal of Arrakis modular is to be able to construct any type of market making strategies on top of any type of dexes/protocols. For accomplish this goal we want to identify and separate the role of each smart contract, and then isolate the part that intend to change for each use cases.

Requirements

Introduction

This section will go through the requirement that Arrakis Modular Architecture should meet. This section will have a functional descriptions and the acceptance criteria associated to it. This acceptance criteria should determine if the future implementation has followed these generals specifications.

Functional Descriptions

Requirement ID : R001
Requirement Name : Deposit on Arrakis Meta Vault
Description : User(s) should be able to participate into the current strategy of the Arrakis Meta Vault strategy. The vault should keep track what his own to this/these user(s).

Requirement ID : R002
Requirement Name : Withdraw from Arrakis Meta Vault
Description : User(s) should be able to cancel his participation into the current strategy of the Arrakis Meta Vault strategy. The vault should give back what he is owning to the user(s).

Requirement ID : R003
Requirement Name : Only owner should be able to set Manager
Description : Owner should be able to set or change manager (the party that will take care of following a strategy). What the vault own to the previous manager should be sent to him.

Requirement ID : R004
Requirement Name : Only owner should be able to whitelist a module
Description : Owner should be able to add a trusted module into the list of trusted modules. After the adding action, manager will be able to use this module if he want.

Requirement ID : R005
Requirement Name : Only owner should be able to blacklist a module
Description : Owner should be able to remove a trusted module from the list of trusted modules. After the removing action, manager will not be able to use this module.

Requirement ID : R006
Requirement Name : Manager should be able to choose the module he want to use.
Description : Manager should be able to choose the module he want to use for his strategy from the list of owner trusted modules. Vault should remove all asset from module before switching to the one chosen by manager.

Requirement ID : R007
Requirement Name : Arrakis Meta Vault should expose totalUnderlying token amount.
Description : Meta vault should compute how much token he own from the current active module. Meta Vault cannot own token himself.

Requirement ID : R008
Requirement Name : Arrakis Meta Vault should expose totalUnderlying token amount at a certain price.
Description : Meta vault should compute how much token he own from the current active module at a virtual price. Meta Vault cannot own token himself.

Requirement ID : R009
Requirement Name : Arrakis Meta Vault should expose init amounts of token0 and token1 needed to creating position initially.
Description : Meta vault should expose the initialisation values for the current active module.

Requirement ID : R010
Requirement Name : Arrakis Meta Vault should expose a helper function that return payload for token0 transfer .
Description : Vault will not receive token, but he should compute the payload of a transfer/approval that can be sent to token0. This payload will approve/transfer the token to the right recipient (active module).

Requirement ID : R011
Requirement Name : Arrakis Meta Vault should expose a helper function that return payload for token1 transfer .
Description : Vault will not receive token, but he should compute the payload of a transfer/approval that can be sent to token1. This payload will approve/transfer the token to the right recipient (active module).

Arrakis Modular Architecture

ArrakisMetaVault

Inheritance

Errors

  • SameModule
    • should be triggered when manager if switching active module but the chosen module is already active.
  • NotWhitelistedModule
    • should be triggered when owner want to blacklist a module, but the module is not a trusted module.
  • AlreadyWhitelisted
    • should be triggered when owner want to whitelist a module, but the module is already a trusted module.
  • ActiveModule
    • should be triggered when owner want to blacklist a module, but the module is the active module.
  • CallFailed
    • should be triggered when call fail (not needed?).
  • AddressZero
    • should be triggered if an inputed address is equal to address zero.
  • Token0GtToken1
    • should be triggered during creation inputed token0 address is bigger than token1 address, that means the addresses have been inverted.

Events

  • LogDeposit
    • depositor (address): the depositor address that owns the tokens deposited.
    • proportion (uint256): the proportion of current liquidity sitting on active module the user wanted to add.
    • amount0 (uint256): how much token0 was needed to add proportion of initial module position.
    • amount1 (uint256): how much token1 was needed to add proportion of initial module position.
  • LogWithdraw
    • receiver (address): the receiver address that the will receive tokens of the withdrawal.
    • proportion (uint256): the proportion of current liquidity sitting on active module the user wanted to remove.
    • amount0 (uint256): how much token0 was withdrawn to remove proportion of initial module position.
    • amount1 (uint256): how much token1 was withdrawn to remove proportion of initial module position.
  • LogSetModule
    • oldModule (address): address of the previous active module.
    • newModule (address): address of the new active module.
  • LogSetManager
    • oldManager (address): address of the previous manager.
    • newManager (address): address of the new manager.
  • LogWhitelistModule
    • modules (address[]): list of address whitelisted by owner.
  • LogBlacklistModule
    • modules (address[]): list of address blacklisted by owner.

Public constant properties

PIPS : base value to compute share.

  • constant
  • uint24
  • value 1e6 = 1_000_000

Public properties

token0 : address of the smallest (in terms of address) token of the pair.

  • immutable
  • address

token1 : address of the biggest (in terms of address) token of the pair.

  • immutable
  • address

module: address of arrakis module used to interact with dexes.

  • IArrakisLPModule

manager: address of manager that will LPs fund on module.

  • IManager

Internal properties

_whitelistedModules : list of whitelisted modules

  • EnumerableSet.AddressSet

Constructor

  • token0_ : address of the smallest token of the token pair.
    • address.
    • should not be address zero.
    • should be smaller than token1_.
  • token1_ : address of the biggest token of the token pair.
    • address.
    • should not be address zero.
    • should be smaller than token1_.
  • module_ : address of the module we want to initialise the vault with.
    • address.
    • should not be address zero.
  • manager_ : address of the manager that will manage the module.
    • address.
    • should not be address zero.
  • owner_ : address of the owner of the vault, he will be able to set the module, whitelist and blacklist them.
    • address.
    • should not be address zero.

checks

  • token0_ should not be address zero, if so trigger AddressZero error.
  • token1_ should not be address zero, if so trigger AddressZero error.
  • token0_ should greater than token1_, if so trigger Token0GtToken1.
  • module_ should not be address zero, if so trigger AddressZero error.
  • manager_ should not be address zero, if so trigger AddressZero error.
  • owner_ should not be address zero, if so trigger AddressZero error.

effects

  • set token0 equal to token0_.
  • set token1 equal to token1_.
  • set module equal to module_.
  • set manager equal to manager_.
  • set _owner equal to owner_ by calling _initializeOwner of Ownable.

State modifying public functions

setModule

inputs

  • module_ (address): address of the whitelisted address to set it as active module.
  • payloads_ (bytes []): array of payloads needed to call after making module_ active.

checks

  • check module_ is not address zero.
  • check module_ is whitelisted.
  • check module_ is not already active, if not revert with SameModule error.
  • check if caller is manager.

effects

  • set _module (address) equal to module.
  • set module equal to module_.

interactions

  • remove liquidity from current module, IArrakisLPModule.withdraw with _module as recipient and PIPS as proportion, that we are withdrawing everything and send it to the module.
  • low level call module for each payload inside payloads.

asserts

  • check each payload call if the call didn't revert => if so trigger CallFailed.

events

  • emit event LogSetModule with _module and module.

setManager

inputs

  • manager_ (address): address of the new manager.

checks

  • check manager_ is not address zero.
  • check manager_ is not already manager.
  • check if caller is _owner.

effects

interactions

  • withdraw current fee balance of manager, by callingIArrakisLPModule.withdrawManagerBalance.
  • set _manager equal to manager.
  • set manager equal to manager_.

asserts

events

  • emit event LogSetManager with _manager and manager.

whitelistModule

inputs

  • modules_ (address[]): list of addresses that _owner want to whitelist.

checks

  • check modules_ length is bigger than zero.
  • check any module is not already whitelisted, if so revert with WhitelistedModule.
  • check if caller is _owner.

effects

  • add each module of modules_ inside modules.

interactions

asserts

events

  • emit event LogWhiteListedModules with _modules.

blacklistModule

inputs

  • modules_ (address[]): list of addresses that _owner want to blacklist.

checks

  • check modules_ length is bigger than zero.
  • check any module is already whitelisted, if so revert with NotWhitelistedModule.
  • check any module is not the current active module, if so revert with ActiveModule error.
  • check if caller is _owner.

effects

  • remove each module of modules_ inside modules.

interactions

asserts

events

  • emit event LogBlackListedModules with _modules.

State modifying internal functions

_deposit

inputs

  • depositor_ (address): address that will receive the underlying assets resulting of burn LP token.
  • proportion_ (uint256): the proportion of current liquidity we want to add.

checks

effects

interactions

  • call module.deposit with depositor_ and proportion_, store returned values inside _amount0 and _amount1.

asserts

events

  • emit event LogDeposit with msg.sender (as depositer) and proportion_.

return values

  • return _amount0 and _amount1.

_withdraw

inputs

  • receiver_ (address): address that will receive the underlying assets resulting of burn LP token.
  • proportion_ (uint256): the proportion of current liquidity we want to remove.

checks

effects

interactions

  • call module.deposit with receiver_ and proportion_, store returned values inside _amount0 and _amount1.

asserts

events

  • emit event LogWithdraw with msg.sender (as depositor), receiver_ and proportion_.

return values

  • return _amount0 and _amount1.

View public functions

totalUnderlying

inputs

internal logic

  • call module.totalUnderlying, save returned values inside _amount0 (uint256) and _amount1 (uint256).

return values

  • return _amount0 and _amount1

totalUnderlyingAtPrice

inputs

  • sqrtPrice_ (uint256): square root price at which level we want to get how underlying tokens we will get.

internal logic

  • call module.totalUnderlyingAtPrice with sqrtPrice_, save returned values inside _amount0 (uint256) and _amount1 (uint256).

return values

  • return _amount0 and _amount1

getInits

inputs

internal logic

  • call module.getInits , save returned values inside _init0 (uint256) and _init1 (uint256).

return values

  • return _init0 and _init1

whitelistedModules

inputs

internal logic

return values

  • return _whitelistedModules.values.

getApproval0Payload

inputs

  • _amount0 (uint256): amount of token0 we will deposit

internal logic

  • check if _amount0 is greater than zero.
  • create call data for approving module amount0 of token0, store the call data into _approve0Payload (bytes).

return values

  • return _approve0Payload

getApproval1Payload

inputs

  • amount1 (uint256): amount of token1 we will deposit

internal logic

  • check if _amount1 is greater than zero.
  • create call data for approving module amount1 of token1, store the call data into _approve1Payload (bytes).

return values

  • return _approve1Payload

ArrakisMetaVaultOwed

Inheritance

  • ArrakisMetaVault

Public state modifying functions

deposit

inputs

  • proportion_ (uint256): the proportion of current liquidity we want to add.

checks

effects

  • call _deposit with msg.sender as and proportion_, store returned values inside _amount0 (uint256) and _amount1 (uint256).

interactions

assertions

events

return values

  • return _amount0 and _amount1.

withdraw

inputs

  • receiver_ (address): the address that will receive the tokens.
  • proportion_ (uint256): the proportion of current liquidity we want to add.

checks

  • check that receiver_ is not address zero, if so trigger AddressZero error.

effects

  • call _withdraw with receiver_ and proportion_, store returned values inside _amount0 (uint256) and _amount1 (uint256).

interactions

assertions

events

return values

  • return _amount0 and _amount1.

ArrakisMetaVaultToken

Inheritance

  • ArrakisMetaVault
  • ERC20

Events

  • LogMint
  • LogBurn

Errors

  • MintZero
  • BurnZero
  • BurnOverflow

Public properties

_name: name of the vault token.

  • string
  • immutable

_symbol: symbol of the vault token.

  • string
  • immutable

Public state modifying functions

mint

inputs

  • shares_ (uint256): amount of vault token you want to mint.
  • receiver_ (address): address of the vault token receiver.

checks

  • check shares_ is not equal to zero, if so trigger MintZero error.
  • check receiver_ is not equal to address zero, if so trigger AddressZero error.

effects

  • get totalSupply of the vault token and store it inside _totalSupply.
  • compute the _proportion the proportion of shares_ in relation to _totalSupply.
  • mint shares_ amount of vault token for receiver_.

interactions

  • call ArrakisMetaVault._deposit with receiver_ and _proportion, store the returned value inside _amount0 and _amount1.

assertions

events

  • emit event LogMint with share_, receiver_, _amount0 and _amount1.

return values

  • return _amount0 and _amount1.

burn

inputs

  • shares_ (uint256): amount of vault token user want to burn.
  • receiver_ (address): address that will receive the underlying token associated to burning shares_ amount of vault token.

checks

  • check shares_ is not equal to zero, if so trigger BurnZero error.
  • check shares_ is lower than totalSupply, if so trigger BurnOverflow error.
  • check receiver_ is not address zero, if so trigger AddressZero error.

effects

  • get totalSupply of the vault token and store it inside _totalSupply.
  • compute the _proportion the proportion of shares_ in relation to _totalSupply.
  • burn shares_ amount of vault token.

interactions

  • call ArrakisMetaVault._withdraw with _receiver and _proportion, store the returned value inside _amount0 and _amount1.

assertions

events

  • emit event LogBurn with share_, receiver_, _amount0 and _amount1.

return values

  • return _amount0 and _amount1.

name

return values

  • return _name

symbol

return values

  • return _symbol

IArrakisLPModule

Constant properties

  • PIPS (uint256): equal to 1e6 or 1_000_000.

Public properties

  • metaVault : metaVault is the owner of this module, only him can can state modifying functions.

    • IArrakisMetaVault
    • immutable
  • token0 : first token of the token pair

    • IERC20
    • immutable
  • token1 : second token of the token pair

    • IERC20
    • immutable
  • managerBalance0 : manage share of token0 generated fees

    • uint256
  • managerBalance1 : manage share of token1 generated fees

    • uint256
  • managerFeePIPS : manager fees in PIPS

    • uint256

Internal properties

  • _init0 : first token of the token pair, initial value needed.

    • uint256
    • immutable
  • _init1 : second token of the token pair, initial value needed.

    • uint256
    • immutable

Events

  • LogDeposit :
    • depositor (address): address that providers tokens to expand the position.
    • proportion (uint256): the proportion we want to expand.
    • amount0 (uint256): amount of token0 needed to expand the position to proportion.
    • amount1 (uint256): amount of token1 needed to expand the position to proportion.
  • LogWithdraw :
    • receiver (address): address that will receive the tokens.
    • proportion (uint256): the proportion we want to contract.
    • amount0 (uint256): amount of token0 that has been removed position to proportion.
    • amount1 (uint256): amount of token1 that has been removed position to proportion.
  • LogSetManagerFeePIPS:
    • manager (address): manager of metaVault.
    • newFeePIPS (uint24): new manager fees in PIPS.
  • LogWithdrawManagerBalance:
    • manager (address): manager of metaVault.
    • managerBalance0 (uint256): amount of token0 of manager fees removed from modules.
    • managerBalance1 (uint256): amount of token1 of manager fees removed from modules.

Errors

  • OnlyMetaVault: function can only be called by metaVault.
  • OnlyMetaVaultManager: function can only be called by metaVault.manager.

Public state modifying functions

  • withdraw
    • can only be called by metaVault.
    • take as inputs parameters receiver of the tokens that will remove from the strat and the proportion of the position we want to remove.
  • deposit
    • can only be called by metaVault.
    • take as inputs parameters depositor of the tokens that will add to the strat and the proportion of the position we want to add.
  • withdrawManagerBalance
    • send managerBalance0 of token0 and managerBalance1 of token1 to metaVault.manager and set managerBalance0 and managerBalance1 to zero.
  • setManagerFeePIPS
    • can only be called by metaVault.manager.
    • before setting the new fees, we can collect fees that has been already generated.
    • set the new manager fees.
  • getInits
    • send back the init0 and init1.
  • totalUnderlying
    • send back how much of token0 and token1 are sitting on the strategy.
  • totalUnderlyingAtPrice
    • simulate and send back how much of token0 and token1 are sitting on the strategy for a specific price.

IManager

Inheritance

  • Ownable

Internal properties

  • _whitelistedVault: list of metaVault managed.
    • Enumerable.AddressSet

Events

  • LogWhitelistVault :
    • vaults (address []): list of vault that has been added for management.
  • LogBlacklistVault :
    • vaults (address []): list of vault that has been removed for management.
  • LogRebalance :
    • vault (address): address of the vault that has been rebalance.
    • payloads (bytes []): payloads needed to rebalance the vault.

Errors

Public state modifying functions

withdrawManagerBalance

  • this function get a specific recipient that will collect vault manager fees from vault.module.withdrawManagerBalance and the token0 / token1 balance sitting on the manager contract.
  • recipient should be different than address zero.
  • vault should be whitelisted.
  • only callable by owner

whitelistVault

  • this function is used by manager to add a array of vaults to the managed vaults list.
  • any of the vault should be whitelisted.
  • only callable by owner.

blacklistVault

  • this function is used by manager to remove a array of vaults to the managed vaults list.
  • all vaults should be whitelisted.
  • call vault.module.withdrawManagerBalance for every vaults of this list with recipient equal to manager.
  • only callable by owner.

rebalance

  • this function is used by manager to rebalance a vault, calling functions of the active module of vault.
  • this function can be more or less trusted or permissionless.
  • only callable by owner.

setModule

  • this function is used by manager to change the module of a vault, by calling metaVault.setModule.
  • vault should be whitelisted.
  • only callable by owner.

setManagerFeePIPS

  • this function is used by manager to change the module of a vault, by calling metaVault.module.setManagerFeePIPS.
  • vault should be whitelisted.
  • only callable by owner.

Public functions

whitelistedVault

  • this function is used to get the list of vaults managed by this manager.
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

No branches or pull requests

1 participant