spartan-protocol / spartanswap-contracts

📃 Spartan Protocol Smart Contracts V1 - V2
20 stars 6 forks source link

Spartan Protocol - Incentivised Liquidity Powered By SPARTA

Spartan Protocol is a liquidity pool protocol that allows token-agnostic provision of liquidity. Traders can swap between tokens at arbitrarily low fees, but a liquidity-sensitive fee maximises revenue for liquidity providers during periods of high demand.

The Spartan Protocol can also facilitate the following features:

Architecture

The following contracts manage the protocol:

1) BASE Contract (Sparta Token Contract) 2) DAO Contract (Manages Governance) 3) UTILS Contract (Stateless contract that manages core math and helper functions) 4) ROUTER Contract (Manages how liquidity is moved around the system) 5) POOL Contract (Holds funds and state for each pool) 6) SYNTH Contract (Holds Lps and state for each synthetic) 7) SYNTHFACTORY Contract (Creates a synthetic token from curated Pools) 8) POOLFACTORY Contract (Creates a pool) 9) SYNTHVAULT Contract (Holds funds and state for members) 10) DAOVAULT Contract (Holds funds and state for members) 11) RESERVE Contract (Holds emissions from base, grants funds to grantors) 12) BONDVAULT Contract (Holds LP funds and state for bond members)

BASE is the source-of-truth for the location of the DAO, as well as minting and distributing incentives.

DAO is the source-of-truth for the location of the ROUTER, UTILS,DAOVAULT,POOLFACTORY,SYNTHFACTORY, RESERVE as well as distributing rewards and managing how the system upgrades itself. It has goverance features that use a member's claim on BASE in each pool to attribute voting weight. The DAO can upgrade itself, as well as amending some features in the BASE contract.

UTILS contains utility and math functions, and can be upgraded by the DAO.

ROUTER contains state and business logic for moving funds, and can be upgraded by the DAO. Users interact with the ROUTER.

POOL holds the funds for each pool, as well as state. It asks the DAO for the location of UTILS which has core math relating to how swaps and liquidity is provisioned, such as calculating fees.

Addresses

WBNB - 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c

Deploy Process

The contracts are to be deployed and then connected together. The DEPLOYER (EOA) has initial DAO privileges in order to manage the process. DEPLOYER should be purged when the system is stable.

1) Deploy SPARTA 2) Deploy SYNTHVAULT(SPARTA.address, Dao.address) 3) Deploy UTILS(SPARTA.address, Dao.address) 4) Deploy ROUTER(SPARTA.address, wbnb.address, Dao.address) 5) Deploy DAOVAULT(SPARTA.address, Dao.address) 6) Deploy BONDVAULT(SPARTA.address, Dao.address) 8) Deploy POOLFACTORY(SPARTA.address, wbnb.address, Dao.address) 9) Deploy SYNTHFACTORY(SPARTA.address, wbnb.address, Dao.address) 10) Deploy RESERVE(SPARTA.address) 11) Set (router.address, utils.address, daoVault.address, poolFactory.address, synthFactory.address, SPReserve.address) in DAO 12) Set dao.address in SPARTA 13) Set (router.address, utils.address, synthV.address, Dao.address) in RESERVE 14) Call start() in RESERVE

Upgrade Process

Goverance should pass a proposal electing a new address.

UTILS

Once passed, the DAO will know the new UTILS contract, and return it when queried (by the ROUTER).

Critical - the new UTILS contract must be inspected for malicious code before allowing an upgrade.

ROUTER

Once passed, the DAO will know the new ROUTER contract, and return it when queried.

Since the ROUTER holds state, the new ROUTER may or may not need state migrated in from the old ROUTER. The state includes:

The new Router may instead want to query the old router for the registry, in addition to managing its own.

DAO

Once passed, the DAO will tell the BASE contract of the new DAO. POOL will now know, because it asks BASE for the location.

RESERVE

This address receives emissions from BASE. The DAO can set a RESERVE address.

BondVault Design

The BONDVAULT holds state and LP tokens for all members who perform a bond() via the DAO. Contains logic for calculating member weights and claimable LP tokens.

DAO Design - Governance

Members firstly lock Spartan Protocol liquidity tokens in the DAOVault, which allow a claim on BASE in each pool to be detected and summed. Importantly, goverance is on-market and liquid - whilst locking another member can purchase BASE off existing members and lock. This reduces existing member weight.

Proposals are a 3-step process:

1) Create a proposal with parameters. 2) Vote for that proposal, if passing quorum, then proceed into a cool-off period in "finalising" state. 3) Once finalising, and past cool-off, anyone can call and finalise in order to automate the actions of the proposal on the system.

DAO Design - Thresholds

DAO Design - Safety

Proposals that upgrade critical infrastructure require Majority:

All other proposals require Quorum:

During the Cool-Off period, a competing proposal that has Minority vote-weight, can call in and veto a finalising Quorum proposal. A scenario is as follows:

1) A questionable Proposal to grant a large holder some funds, gets past 50% vote and enters cool-off. 2) Minority (16.6%) members are concerned it is not in the best interest of the system, so thus have the cool-off period to vote for a competing proposal that can be used to neutralise (1). 3) The competing proposal is not finalised/completed, as it also needs to achieve Quorum first.

DAO Design - Functionality

DaoVault Design

The DAOVAULT holds state and LP tokens for all members who perform a deposit() via the DAO. Contains logic for calculating member weights.

Pool Design

Each POOL contains logic and holds funds and state. The only way to get funds out of the POOL is to send it funds first (assets or liquidity tokens).

The pool asks the UTILS contract for logic relating to adding/removing liquidity, as well as swapping, so in the future, logic can be changed. However an upgrade to a malicous UTILS contract could compromise funds in the system.

PoolFactory Design

The POOLFACTORY manages the creation and status of all Spartan pools.

Reserve Design

The BASE contract mints a certain number of coins every era and sends them to the RESERVE.

The mint amount is set by (300m-totalSupply)/emissionCurve which will mint a slowly decreasing amount each day. The feeBurn in BASE enforces a deflationary burn to counter the emissions that gradually increases as the supply increases to counter the emissions.

Users lock LP tokens in the DAO and can call harvest() as often as they want, although since the reserve in the DAO depletes, it favours those who call it more frequently. If the erasToEarn is set to 30 days, then after the final drop, it will take 30 days for all rewards to be consumed. However, since new rewards are sent there every day, the velocity of emissions should be fairly constant.

Router Design

The ROUTER facilitates movement of funds from users into pools, containing business logic for adding/removing liquidity, swapping and managing synths.

The Router does not hold funds.

Synth Design

Each SYNTH contains logic and holds LP tokens and state. Minting synths requires the relevant POOL to send LP units to the SYNTH and call mintSynth().

SynthFactory Design

The SYNTHFACTORY manages the creation and status of all Spartan synth assets.

Utils Design

UTILS works as both a web3 aggregrator (one call that makes several EVM calls, returning objects), as well as the core arithmetic of the system.

It is also used to retrieve state from the router, tokens and pools. DApps can read from UTILS, write to ROUTER.

The UTILS contract has the following:

The UTILS contract can be upgraded, but upgrading it to a malicious contract can compromise funds in the system by changing logic to favour an attacker.

Future Features

Testing - Buidler

The test suite uses Buidler as the preferred testing suite, since it compiles and tests faster. The test suite implements 7 routines that can be tested individually.

npx buidler compile

Execute all at once:

npx builder test

Or execute individually:

npx builder test/1_base.js