SpartanDev: 13SEP21 - 19SEP21

Dev Update

SpartanDev: 13SEP21 - 19SEP21

Private testnet testing almost at completion, preparing for public testnet. The C4 contest's audit report has gone public.

SpartanDev: 13SEP21 - 19SEP21

Summary

Hello Spartans! Well; another week has passed with us now seeing the private testnet testing almost squared-off; just some time-based tests & preparations before we redeploy fresh for a public testnet round!

This week saw the C4 report go live; massive thanks to the C4 team, wardens, judges, contributors & donators who helped make that happen. The plan is for some contributors to band together and do an article on the top issues explaining them and showing the post-contest mitigations in the new code.

Spartan Protocol Contest
Hack DeFi. Compete. Get paid.

The DApp has been enjoying the private testnet period as a great opportunity to pad out the features that will be available on V2 launch and try to automate as many UX-based edge cases as possible to make it easier for the users to interact with the protocol. Follow along with the updates from the past week below!

Call for TestNet Funds

Please if you have the time, learn how to claim free testnet assets to stockpile for public testnet or send them over to the contributor wallet to help them test!

BSC Testnet Funds - The Faucet
The BSC testnet faucet is awaiting your claim Spartans! Go forward and dip into the sweet faucet in preparation for testnet.

Wednesday feeBurn Update

Spartan Socials - Twitter

Tweet of the Week:

SpartanSocials - Medium

SpartanSocials - Telegram


Contributor's Focus

CodeArena Contest

COMPLETED ✅ — Triage and prioritise the feedback submitted from the CodeArena wardens during the contest to prepare for the judges

COMPLETED ✅ — Work through the post-contest tasks with the C4 judges & team for the eventual allocation of awards to security wardens

COMPLETED ✅ — C4 Public Report

IN PROGRESS — Post-contest article on the top issues

SPARTA V2 (Token)

COMPLETED ✅ — Work with DEXs & aggregators to ensure up-to-date information on the new SPARTA token (retiring the previous contract address)

COMPLETED ✅ — Work with token-tracking informational websites to ensure new token info is up-to-date (BSCscan, CoinGecko, CoinMarketCap)

SpartanContracts

COMPLETED ✅ — Sort and prioritise all CodeArena submissions into contract scopes along with tags based on ‘actionable’ or ‘discussion points’

COMPLETED ✅ — Implementing refinements to contracts to address C4 & contributor feedback since the C4 contest code-freeze

COMPLETED ✅ — Rebuild automated testing & start private testnet

Deploy V2 to public testnet

Deploy completed V2 contracts to BSC mainnet

DAppV2

COMPLETED ✅ — Prepare DAppV2 for testnet deploy

IN PROGRESS — Continue updating during private testnet

Continue updating during public testnet

After Mainnet

(Optional/Side-Task) — Work with aggregators to connect to the SPARTA pools

(Optional/Side-Task) — Work with CMC/CoinGecko to feed in the SPARTA pool info

Set up a reliable index of history scoped to contracts (use this for positions page etc)

Use the new testnet subgraph to build a more lightweight positions page for V2

Enable Bond allocations to replenish TVL into the V2 pools

March onwards with our original goals of building the decentralised, yield-generating synthetics protocol on Binance Smart Chain


GitHub Activity — Spartan Contracts v2

Branch: PostC5

contracts/BondVault.sol

  1. delistBondAsset() - changed the require() for isListed[_pool] to an if() instead to allow a Dao proposal for 'delist a curated asset' to complete even if it has already been delisted from bond

contracts/Dao.sol

  1. Removed ERAS_TO_EARN:
  • Changing erasToEarn via a DAO proposal has been reviewed and decided as not a particularly important variable to press on as a DAO. Its effects on the protocol are also not entirely understandable for the regular peers that make up the DAO

2. Added DAO_CLAIM:

  • Whilst still technical to explain in granular detail; changing the DAOVault claim % is much more understandable for the DAO peers and has hence been added to the proposals list.
  • There is a hard-coded limit of 15% to prevent a greedy DAO from speeding up the RESERVE drain and inflating the circulating supply more than intended.
  • This will act more as a way for the DAO to 'reduce' or completely 'stop' the claim % rather than inflate it

3. Added SYNTH_CLAIM:

  • A similar variable lives in the SynthVault and the vaults may not necessarily need to have the same claim %
  • For instance, if the liquidity providers decide the SynthVault is generative too much attention; they may vote to reduce the claim %
  • This will act to regulate the incentive that drives people into the SynthVault (and regulate the circulating supply speed and long-term claimable RESERVE size for the DAOVault & dividends)
  • There is a hard-coded limit of 15% to prevent a greedy DAO from speeding up the RESERVE drain and inflating the circulating supply more than intended.
  • This will act more as a way for the DAO to 'reduce' or completely 'stop' the claim % rather than inflate it

contracts/Pool.sol

  1. Changed oldRate variable to public so the UI can access it for peers to help determine safety levels of pools
  2. addForMember() - changed the oldRate initial rate assignment to factor to 10**18 instead of a square-factor to match the adjusted calc for _safetyCheck()
  3. mintSynth() - changed the synthCap check to use outputAmount (actual synth mint) instead of output (before slip) so that synths can be minted closer to the actual cap
  4. stirCauldron() - changed to public for other contracts to have access to calling it
  5. _safetyCheck() changes:
  • Adjusted currentRate calc to use 10**18 * baseAmount as the numerator instead of baseAmount* baseAmount
  • Moved rateDiffBP assignment inside each relevant if() and else()
  • Made the hourly rate smoothing more aggressive; changed: (currentRate +(oldRate *3) ) /4 to (currentRate + oldRate ) /2 meaning the rate gets 50% closer to the currentRate each hour

6. Removed flipFreeze() as it no longer serves a function; flipping freeze when the ratio is outside the safety zone will just mean it gets flipped back with the next transaction

contracts/Router.sol

  1. Changes to removeLiq lockup during freeze:
  • When removing liquidity there is a check for: isCuratedPool and also Pool(fromPool).freeze() == false
  • If both are true; removeLiq will be locked until the pool's level gets back to its safety zone (or until pool corrects; which gets closer each hour)
  • This means that only the 'protocol value extraction risk' pools ever have this happen; smaller/general pools will continue to operate even outside their safety zones

contracts/Utils.sol

  1. Fixed the baseCap number being handed to the UI in getPoolData()

contracts/synthVault.sol

  1. Added DAO to the permissioned onlyDAO() modifier
  2. harvestSingle() - moved 'lastHarvestTime' assignment/reset to only happen when at the synthCap (SPARTA paid out instead) as Pool.mintSynth() already resets this when it goes to the SynthVault for the member
  3. Added setReserveClaim() setter for the new DAO proposal

test/2_swap.js

  1. Added in safetyCheck automated tests

test/3_dao.js

  1. Removed ERAS_TO_EARN tests
  2. Added DAOCLAIM tests
  3. Added SYNTH_CLAIM tests

GitHub Activity — Spartan DApp v2

Branch: V2TN

Lots of work done again this week on DAppv2! Big thanks to our friendly community member Jacobo for his consistent DApp contributions recently; they have been well received & appreciated!

src/ABI/TN/*.json

  1. Updated ABIs

src/assets/scss/spartan/custom/_input-group.scss

  1. Disabled up/down buttons on inputs

src/assets/scss/spartan/custom/_utilities.scss

  1. Added simple class to hide on iphone5-width screens

src/components/Approval/Approval.js

  1. Made loading spinner smaller

src/components/DataManager/DataManager.js

  1. Cleaned up function-comments (mostly just changed multi-line to single-line)
  2. Refactored out all the chainId checks to variables held in src/utils/web3.js for a smoother transition for the DApp to mainnet
  3. Removed 'wallet' from a lot of static calls to use a randomly-generated default provider instead of the user's specific one (this means the RPC calls will be more distributed and resistant to nodes being down or out of sync)
  4. checkArraysNext() - removed some dependencies:
  • window.localStorage.getItem('network') - we reload the dapp on network change now so this isn't needed
  • wallet.account - we reload the dapp on wallet change now so this isn't needed

5. checkDetails() - removed the getSynthDetails() call. We now do this where required instead of globally (ie. synthVault, synth tab in wallet & swap page)

6. Added in addTxn() calls for all the other txn types:

  • bond.txn, dao.txn, dao.propTxn, pool.txn, sparta.txn, synth.txn & web3.txn
  • Added in a conditional to ensure the item has a txnType to prevent accidental inf loops or broken/unintended data being added to the txnArray

src/components/Drawer/Drawer.js

  1. Added txnDrawer id so that we can access the element from a lookup

src/components/RecentTxns/RecentTxns.js

  1. Added pagination:
  • Calculate the height of the txnDrawer and divide by the intended height of a row (~55px) to get the rows for the screensize of the user
  • Function to filter txnArray to the relevant scope
  • Function to filter that by the intended view based on the active page number
  • Dynamic pagination buttons (could do with some styling and edge-checks)

2. Added in all the other txn types

3. Added helpers to get the formatted txn details

4. Setup a basic template for what details to show (and how to get them)

src/components/WalletSelect/Assets.js

  1. Simplified the watchAsset() logic as this  component is already scoped to token
  2. Added helpers: _getPool(), isSparta() & getUSD()
  3. Assets are now sorted by $USD value
  4. Cleaned up / balanced the structure/margins
  5. Made the component more responsive to all screen sizes
  6. Added in the $USD value for each asset held
  7. Ready for the styling stage

src/components/WalletSelect/LPs.js

  1. Simplified the watchAsset() logic as this  component is already scoped to pool
  2. Added helpers: _getPool() & getUSD()
  3. Assets are now sorted by $USD value
  4. Cleaned up / balanced the structure/margins
  5. Made the component more responsive to all screen sizes
  6. Added in the $USD value for each LP token held, staked & bonded
  7. Ready for the styling stage

src/components/WalletSelect/Synths.js

  1. Simplified the watchAsset() logic as this  component is already scoped to synth
  2. Added helpers: _getPool() & getUSD()
  3. Assets are now sorted by $USD value
  4. Cleaned up / balanced the structure/margins
  5. Made the component more responsive to all screen sizes
  6. Added in the $USD value for each synth token held & staked
  7. Ready for the styling stage

src/components/WalletSelect/WalletSelect.js

  1. Fixed args for getLPWeights()
  2. ChainId checks changed to the new variables in web3.js

src/store/bond/*.js

  1. Added getBondDetails():
  • Removed the bond-related calls from the poolDetails action and siloed them into their own bondDetails object

2. Removed wallet from static calls to use a random-RPC default provider instead

3. Added wallet to some state-changing functions that were missing it (to use signer instead)

src/store/dao/*.js

  1. Fixed memberVoted bool being converted to a string
  2. Added getDaoDetails():
  • Removed the daoVault-related calls from the poolDetails action and siloed them into their own daoDetails object

3. Reformatted functions to get most line-logic on one line (cleaner code)

4. Changed all txns to call (and wait for) parseTxn() before updating the store so that only confirmed txns make it thru. This is also so the txn is run thru the new parser ready for txnDetails/RecentTxns

If you are following along closely or looking to contribute this; the example to follow along with is daoHarvest() which moves the txnType into the parseTxn(txn, txnType) and removes it from the payloadToDispatch() which now only gets the parsed tnx with no array-sibling (this format will be replicated for all txn types once its finalised)

src/store/pool/*.js

  1. Removed wallet from static calls to use a random-RPC default provider instead
  2. Refactor getPoolDetails():
  • Removed daoVault staked (siloed out)
  • Refactored the recentFees & lastMonthFees to only call one or the other based on pool's genesis
  • Removed bondDetails - isMember, bondedLP, claimRate, lastBlockTime (siloed out)
  • Simplified the curated check
  • Simplified the frozen check
  • Added in the oldRate call

3. createPoolADD() - removed unneeded provider logic & changed to a txnType style action

src/store/reserve/*.js

  1. Removed wallet from static calls to use a random-RPC default provider instead

src/store/router/*.js

  1. updatePoolStatus() - changed to a txnType style action

src/store/sparta/*.js

  1. Removed wallet from static calls to use a random-RPC default provider instead
  2. spartaUpgrade() - changed to a txnType style action
  3. fsClaim() - changed to a txnType style action

src/store/synth/*.js

  1. getSynthGlobalDetails() - added in call to get synthCount (we can consider using the length of synthDetails filtered to a valid address instead)
  2. getSynthMinting() - added in this action to call the ROUTER and get the synthMinting status
  3. synthDeposit() - removed unneeded provider logic
  4. createSynth() - changed to a txnType style action

src/store/web3/*.js

  1. getApproval() - removed unneeded provider logic & changed to a txnType style action
  2. watchAsset() - simplified the conditional to use wallet.account instead of sessionstorage (more correct/accurate)

src/utils/helpers.js

  1. Added a simple UNIX -> locale-formatted date helper

src/utils/math/bondVault.js

  1. Updated calcBondedLP() to suit the siloed-out changes

src/utils/math/dao.js

  1. Fixed to use correct calcSwapOutput() return
  2. calcRewardDao() - function name change, cleaned up to fit line-by-line & added in erasToEarn divisor
  3. calcCurrentRewardDao() - function name change, cleaned up to fit line-by-line & uupdated getVaultWeights() to use all 3 siloed-out scopes

src/utils/math/nonContract.js

  1. Cleaned up & updated comments
  2. Added calcLiqValueInBase() to help with the wallet $USD-value additions
  3. getLPWeights() - args updated to include all 3 siloed-out scopes & changed the function to handle them accordingly
  4. getVaultWeights() - args updated to include all 3 siloed-out scopes & changed the function to handle them accordingly
  5. getSynthVaultWeights() - added in function to get the user's staked synthVault weight
  6. getBlockTimestamp() - added function to get the timestamp in the same format as the chain; used this throughout any existing math functions that do the conversion in-function
  7. calcAPY() - updated to suit the changes in poolDetails & added a 0.00 fallback

src/utils/math/router.js

  1. addLiq() - added in missing item from fallback-return
  2. swapTo() - added in an extra return item spartaOut (to track pool balance change accurately in-function/off-chain)
  3. Added math function for stirCauldron() (to get dynamic synthCap)
  4. Updated mintSynth() math
  5. Updated burnSynth() math

src/utils/math/synth.js

  1. Added realise() math function to calculate the premium that would be burned from calling realise()

src/utils/math/synthVault.js

  1. Added calcRewardSynth() math to calculate user's total claimable per era
  2. Added calcCurrentRewardSynth() math to calculate the user's multiple of the total claimable per era and return the raw rewards. This also handles SPARTA out in the case of synthCap

src/utils/math/utils.js

  1. Cleaned up comments and var names used for most returns to make this more readable and understandable for new contributors
  2. getToken() - changed to have a false fallback to make error handling easier
  3. getPool() - changed to have a false fallback to make error handling easier
  4. getSynth() - changed to have a false fallback to make error handling easier
  5. Added in getDao() helper to get relevant daoDetails item
  6. Added in getBond() helper to get relevant bondDetails item
  7. Added in calcActualSynthUnits() function to help with the new realise() math function
  8. calcSwapOutput() refactored out the swap fee calculation to another function calcSwapFee()
  9. Removed a bunch of old math functions that probably arent required

src/utils/web3.js

  1. Updated addresses
  2. Checked performance of the testnet RPCs and commented in/out the good/bad ones; we should look to do this monthly ongoing including the mainnet ones
  3. Added liveChains variable to make dapp-transition to mainnet smoother/easier
  4. Added tempChains variable to make dapp-transition to mainnet smoother/easier
  5. getWalletProvider() now generates a random-RPC simple provider each time
  6. Added parseTxnLogs() as a basis for handling event data and parsing it in a format for RecentTxns/TxnDetails
  7. Added parseTxn() as the parent function for parsing the txn data
  8. clearTxns() updated to suit the changes to adding a txn

src/utils/web3Contracts.js

  1. Finalised the default provider logic (above) and updated the getContract style functions accordingly (if a wallet is handed in; get the wallets provider/signer; otherwise hand in null and get a random-RPC simple provider)

src/views/pages/Bond/Bond.js

  1. Only conditionally show bond if required arrays are loaded
  2. Dispatch getBondDetails() as required in this view
  3. Change the poolDetails -> bondDetails according to the new siloed-out objects

src/views/pages/Bond/BondItem.js

  1. Refactored some logic to make the JSX code cleaner
  2. Fixed the old /pools/ link/route
  3. Change the poolDetails -> bondDetails according to the new siloed-out objects

src/views/pages/Dao/NewProposal.js

  1. setparamValid() is now not a simple > 0 due to the changed param-proposal-types. Added in checks to make sure their validity is checked according to type
  2. Added in isLoading check to avoid excess conditional-check logic in the JSX
  3. Converted the static dao proposal fee to dynamic based on dao.global.daoFee

src/views/pages/Dao/Overview.js

  1. Dispatch for getDaoDetails() as required
  2. Dispatch for getBondDetails() as required
  3. Dispatch for getSynthDetails() as required

src/views/pages/Dao/ProposalItem.js

  1. Added isLoading check
  2. Updated getTimeCancel() to use dynamic dao.global.cancelPeriod instead of static
  3. totalPercent() updated to use new dynamic weight helpers
  4. majorities - added an array of proposal types that require majority consensus
  5. Extended the weightClass() function to also return a numbered weight class for easier conditional checks
  6. Added a canPoll() conditional checker to check if the proposal is ready to have its status checked
  7. Extended status() to handle canPoll() status too
  8. Updated getDetails() function:
  • FLIP_EMISSIONS type will only show the 'on' or 'off' if the proposal is open (otherwise after the proposal it will simply show the opposite of the dynamic status of emissions)
  • Removed ERAS_TO_EARN type logic
  • Added logic to get details of DAO_CLAIM & SYNTH_CLAIM proposal types
  • Added logic to get details of REALISE proposal type including the calculated amount of premium that would be burned if realise() happened at that moment

9. Updated all the weight logic for the front end to be shown and calculated dynamically based on the new contracts

10. Added a pollVotes() button for anyone to call to push the proposal to the next phase (if the proposal meets the requirements)

11. Added date to the bottom of completed proposals to show what date it was proposed

src/views/pages/Dao/components/AssetSelect.js

  1. getDetails() changed function name and rebuilt the function to show the correctly filtered list of relevant assets for each address proposal type

src/views/pages/Dao/types.js

  1. Added REALISE proposal type details
  2. Added SYNTH_CLAIM proposal type details
  3. Added DAO_CLAIM proposal type details
  4. Removed ERAS_TO_EARN

src/views/pages/Home/NewPool.js

  1. Added in edge-case check for minToken amount (just disables button; will need to add dynamic message/button-label)

src/views/pages/Home/PoolItem.js

  1. Refactor the dividend & relevant-conditionals logic

src/views/pages/Pools/LiqAdd.js

  1. If the auto-asset-select asset is of 'hide' status selection will revert to 'bnb'
  2. Removed handleTokenInputChange
  3. Other general changes

src/views/pages/Pools/LiqBond.js

  1. Removed handleTokenInputChange
  2. Updated all the math getters to point to the updated math and return all the items required
  3. Added in whitelist logic to only list the bond listed pools

src/views/pages/Pools/LiqRemove.js

  1. Removed handleTokenInputChange
  2. Other general changes
  3. Added fallback if no pools are listed

src/views/pages/Swap/Swap.js

  1. Dispatch getSynthDetails() & getSynthMinting() as required
  2. Added getFilter() to filter the valid modes based on poolCount & synthCount
  3. Adjusted the auto-asset-select logic based on getFilter()
  4. Extended checkValid() to handle synthMinting, confirmSynth, zapSlip, zapBaseCap, newPool, confirmLockup etc
  5. Removed handleTokenInputChange
  6. Added in newPool confirmation and info (for zapLiq)
  7. Added in mintSynth confirmation & info (for minting synths thru swap page)

src/views/pages/Swap/SwapPair.js

  1. Updated APY and dividend logic

src/views/pages/Synths/Overview.js

  1. Dispatch getSynthDetails() & getSynthMinting() as required
  2. Removed handleTokenInputChange
  3. Added checkValid() logic to check if a txn is valid and return a label accordingly
  4. Added in mintSynth confirmation & info
  5. Added fallback if no synths are deployed

src/views/pages/Vault/Components/DaoDepositModal.js

  1. Simplified this modal a lot
  2. Removed the stages and explorer link/loader etc

src/views/pages/Vault/Components/SynthDepositModal.js

  1. Simplified this modal a lot
  2. Removed the stages and explorer link/loader etc

src/views/pages/Vault/DaoVault.js

  1. Siloed out the dispatch calls:
  • getData() main call triggers on load & timer now only get daoGlobalDetails() & daoMemberDetails()
  • New useEffect for getDaoDetails() & getBondDetails() which only triggers when pool.listedPools updates
  • New useEffect for daoVaultWeight() & bondVaultWeight() which only triggers when pool.poolDetails updates
  • New useEffect for daoDepositTimes() which only triggers when dao.daoDetails updates

2. Added getTotalWeight() helper

3. Updated getClaimable() helper to call the relevant math & added a 0.00 fallback (refactor)

4. Added an isLoading conditional checker

5. Changed the poolDetails -> daoDetails according to the new siloed-out objects

6. Fixed the old /pools/ link/route

src/views/pages/Vault/SynthVault.js

  1. getGlobals() now only gets the getSynthGlobalDetails() on load (and timer)
  2. New uesEffect to only get getSynthDetails() when synth.synthArray updates
  3. New useEffect() to only get synthVaultWeight() when synth.synthDetails updates
  4. Added isLoading
  5. Updated all the weight-relevant logic in the JSX

src/views/pages/Vault/SynthVaultItem.js

  1. Updated APY() to use bigNumber where required and return the value
  2. Refactored out formatDate() & getFeeBurn()
  3. Refactored out the math in getClaimable() to the relevant math file
  4. Added checkValid() helper

Project Information

  • Website: https://spartanprotocol.org/
  • DApp: https://dapp.spartanprotocol.org/
  • GitBook (Docs): https://docs.spartanprotocol.org/
  • GitHub: https://github.com/spartan-protocol

Community Contribution

Spartan Protocol is at its core, a community-driven and led project. In this vein, the more contributors the better. There is a great opportunity for community members to contribute by making LP reward analysis tools, etc.

Recently, community members have been graciously funnelling in to contribute to explainer articles, ideas and even $SPARTA donations to support the growth of the platform.

Binance Smart Chain TestNet Faucet

Contributors TestNet Wallet

Got some spare BSC TestNet assets? Please throw some to the contributors getting ready for testing! Or build up your testnet balances via the faucet to help contribute to balancing the pools in the upcoming testnet.

  • 0x3d2aCFafd10600896C90a325c31700B3E1E2D791

Engage with the community and contributors

Where to find out about all the latest updates or suggest improvements — get involved.