SpartanDev: 13SEP21 - 19SEP21
Private testnet testing almost at completion, preparing for public testnet. The C4 contest's audit report has gone public.
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.
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!
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
delistBondAsset()
- changed therequire()
forisListed[_pool]
to anif()
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
- 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
- Changed
oldRate
variable topublic
so the UI can access it for peers to help determine safety levels of pools addForMember()
- changed theoldRate
initial rate assignment to factor to10**18
instead of a square-factor to match the adjusted calc for_safetyCheck()
mintSynth()
- changed the synthCap check to useoutputAmount
(actual synth mint) instead ofoutput
(before slip) so that synths can be minted closer to the actual capstirCauldron()
- changed topublic
for other contracts to have access to calling it_safetyCheck()
changes:
- Adjusted
currentRate
calc to use10**18 * baseAmount
as the numerator instead ofbaseAmount* baseAmount
- Moved
rateDiffBP
assignment inside each relevantif()
andelse()
- Made the hourly rate smoothing more aggressive; changed:
(currentRate +(oldRate *3) ) /4
to(currentRate + oldRate ) /2
meaning the rate gets 50% closer to thecurrentRate
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
- Changes to removeLiq lockup during freeze:
- When removing liquidity there is a check for:
isCuratedPool
and alsoPool(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
- Fixed the
baseCap
number being handed to the UI ingetPoolData()
contracts/synthVault.sol
- Added DAO to the permissioned
onlyDAO()
modifier harvestSingle()
- moved 'lastHarvestTime' assignment/reset to only happen when at the synthCap (SPARTA paid out instead) asPool.mintSynth()
already resets this when it goes to the SynthVault for the member- Added
setReserveClaim()
setter for the new DAO proposal
test/2_swap.js
- Added in
safetyCheck
automated tests
test/3_dao.js
- Removed
ERAS_TO_EARN
tests - Added
DAOCLAIM
tests - 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
- Updated ABIs
src/assets/scss/spartan/custom/_input-group.scss
- Disabled up/down buttons on inputs
src/assets/scss/spartan/custom/_utilities.scss
- Added simple class to hide on iphone5-width screens
src/components/Approval/Approval.js
- Made loading spinner smaller
src/components/DataManager/DataManager.js
- Cleaned up function-comments (mostly just changed multi-line to single-line)
- Refactored out all the
chainId
checks to variables held insrc/utils/web3.js
for a smoother transition for the DApp to mainnet - 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)
checkArraysNext()
- removed some dependencies:
window.localStorage.getItem('network')
- we reload the dapp on network change now so this isn't neededwallet.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
- Added
txnDrawer
id so that we can access the element from a lookup
src/components/RecentTxns/RecentTxns.js
- 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
- Simplified the
watchAsset()
logic as this component is already scoped totoken
- Added helpers:
_getPool()
,isSparta()
&getUSD()
- Assets are now sorted by $USD value
- Cleaned up / balanced the structure/margins
- Made the component more responsive to all screen sizes
- Added in the $USD value for each asset held
- Ready for the styling stage
src/components/WalletSelect/LPs.js
- Simplified the
watchAsset()
logic as this component is already scoped topool
- Added helpers:
_getPool()
&getUSD()
- Assets are now sorted by $USD value
- Cleaned up / balanced the structure/margins
- Made the component more responsive to all screen sizes
- Added in the $USD value for each LP token held, staked & bonded
- Ready for the styling stage
src/components/WalletSelect/Synths.js
- Simplified the
watchAsset()
logic as this component is already scoped tosynth
- Added helpers:
_getPool()
&getUSD()
- Assets are now sorted by $USD value
- Cleaned up / balanced the structure/margins
- Made the component more responsive to all screen sizes
- Added in the $USD value for each synth token held & staked
- Ready for the styling stage
src/components/WalletSelect/WalletSelect.js
- Fixed args for
getLPWeights()
ChainId
checks changed to the new variables in web3.js
src/store/bond/*.js
- Added
getBondDetails()
:
- Removed the bond-related calls from the
poolDetails
action and siloed them into their ownbondDetails
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
- Fixed
memberVoted
bool being converted to a string - Added
getDaoDetails()
:
- Removed the daoVault-related calls from the
poolDetails
action and siloed them into their owndaoDetails
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
- Removed
wallet
from static calls to use a random-RPC default provider instead - Refactor
getPoolDetails()
:
- Removed daoVault
staked
(siloed out) - Refactored the
recentFees
&lastMonthFees
to only call one or the other based on pool'sgenesis
- 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
- Removed
wallet
from static calls to use a random-RPC default provider instead
src/store/router/*.js
updatePoolStatus()
- changed to atxnType
style action
src/store/sparta/*.js
- Removed
wallet
from static calls to use a random-RPC default provider instead spartaUpgrade()
- changed to atxnType
style actionfsClaim()
- changed to atxnType
style action
src/store/synth/*.js
getSynthGlobalDetails()
- added in call to get synthCount (we can consider using the length ofsynthDetails
filtered to a valid address instead)getSynthMinting()
- added in this action to call theROUTER
and get thesynthMinting
statussynthDeposit()
- removed unneededprovider
logiccreateSynth()
- changed to atxnType
style action
src/store/web3/*.js
getApproval()
- removed unneededprovider
logic & changed to atxnType
style actionwatchAsset()
- simplified the conditional to usewallet.account
instead ofsessionstorage
(more correct/accurate)
src/utils/helpers.js
- Added a simple UNIX -> locale-formatted date helper
src/utils/math/bondVault.js
- Updated
calcBondedLP()
to suit the siloed-out changes
src/utils/math/dao.js
- Fixed to use correct
calcSwapOutput()
return calcRewardDao()
- function name change, cleaned up to fit line-by-line & added inerasToEarn
divisorcalcCurrentRewardDao()
- function name change, cleaned up to fit line-by-line &u
updatedgetVaultWeights()
to use all 3 siloed-out scopes
src/utils/math/nonContract.js
- Cleaned up & updated comments
- Added
calcLiqValueInBase()
to help with the wallet $USD-value additions getLPWeights()
- args updated to include all 3 siloed-out scopes & changed the function to handle them accordinglygetVaultWeights()
- args updated to include all 3 siloed-out scopes & changed the function to handle them accordinglygetSynthVaultWeights()
- added in function to get the user's staked synthVault weightgetBlockTimestamp()
- 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-functioncalcAPY()
- updated to suit the changes inpoolDetails
& added a0.00
fallback
src/utils/math/router.js
addLiq()
- added in missing item from fallback-returnswapTo()
- added in an extra return itemspartaOut
(to track pool balance change accurately in-function/off-chain)- Added math function for
stirCauldron()
(to get dynamic synthCap) - Updated
mintSynth()
math - Updated
burnSynth()
math
src/utils/math/synth.js
- Added
realise()
math function to calculate the premium that would be burned from callingrealise()
src/utils/math/synthVault.js
- Added
calcRewardSynth()
math to calculate user's total claimable per era - Added
calcCurrentRewardSynth()
math to calculate the user's multiple of the total claimable per era and return the raw rewards. This also handlesSPARTA
out
in the case ofsynthCap
src/utils/math/utils.js
- Cleaned up comments and var names used for most returns to make this more readable and understandable for new contributors
getToken()
- changed to have afalse
fallback to make error handling easiergetPool()
- changed to have afalse
fallback to make error handling easiergetSynth()
- changed to have afalse
fallback to make error handling easier- Added in
getDao()
helper to get relevantdaoDetails
item - Added in
getBond()
helper to get relevantbondDetails
item - Added in
calcActualSynthUnits()
function to help with the newrealise()
math function calcSwapOutput()
refactored out the swap fee calculation to another functioncalcSwapFee()
- Removed a bunch of old math functions that probably arent required
src/utils/web3.js
- Updated addresses
- 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
- Added
liveChains
variable to make dapp-transition to mainnet smoother/easier - Added
tempChains
variable to make dapp-transition to mainnet smoother/easier getWalletProvider()
now generates a random-RPC simple provider each time- Added
parseTxnLogs()
as a basis for handling event data and parsing it in a format for RecentTxns/TxnDetails - Added
parseTxn()
as the parent function for parsing the txn data clearTxns()
updated to suit the changes to adding a txn
src/utils/web3Contracts.js
- 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 innull
and get a random-RPC simple provider)
src/views/pages/Bond/Bond.js
- Only conditionally show bond if required arrays are loaded
- Dispatch
getBondDetails()
as required in this view - Change the
poolDetails
->
bondDetails
according to the new siloed-out objects
src/views/pages/Bond/BondItem.js
- Refactored some logic to make the JSX code cleaner
- Fixed the old
/pools/
link/route - Change the
poolDetails
->
bondDetails
according to the new siloed-out objects
src/views/pages/Dao/NewProposal.js
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- Added in
isLoading
check to avoid excess conditional-check logic in the JSX - Converted the static dao proposal fee to dynamic based on
dao.global.daoFee
src/views/pages/Dao/Overview.js
- Dispatch for
getDaoDetails()
as required - Dispatch for
getBondDetails()
as required - Dispatch for
getSynthDetails()
as required
src/views/pages/Dao/ProposalItem.js
- Added
isLoading
check - Updated
getTimeCancel()
to use dynamicdao.global.cancelPeriod
instead of static totalPercent()
updated to use new dynamic weight helpersmajorities
- added an array of proposal types that require majority consensus- Extended the
weightClass()
function to also return a numbered weight class for easier conditional checks - Added a
canPoll()
conditional checker to check if the proposal is ready to have its status checked - Extended
status()
to handlecanPoll()
status too - 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 ifrealise()
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
getDetails()
changed function name and rebuilt the function to show the correctly filtered list of relevant assets for eachaddress
proposal type
src/views/pages/Dao/types.js
- Added
REALISE
proposal type details - Added
SYNTH_CLAIM
proposal type details - Added
DAO_CLAIM
proposal type details - Removed
ERAS_TO_EARN
src/views/pages/Home/NewPool.js
- 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
- Refactor the dividend & relevant-conditionals logic
src/views/pages/Pools/LiqAdd.js
- If the auto-asset-select asset is of 'hide' status selection will revert to 'bnb'
- Removed
handleTokenInputChange
- Other general changes
src/views/pages/Pools/LiqBond.js
- Removed
handleTokenInputChange
- Updated all the math getters to point to the updated math and return all the items required
- Added in whitelist logic to only list the bond listed pools
src/views/pages/Pools/LiqRemove.js
- Removed
handleTokenInputChange
- Other general changes
- Added fallback if no pools are listed
src/views/pages/Swap/Swap.js
- Dispatch
getSynthDetails()
&getSynthMinting()
as required - Added
getFilter()
to filter the valid modes based onpoolCount
&synthCount
- Adjusted the auto-asset-select logic based on
getFilter()
- Extended
checkValid()
to handlesynthMinting
,confirmSynth
,zapSlip
,zapBaseCap
,newPool
,confirmLockup
etc - Removed
handleTokenInputChange
- Added in
newPool
confirmation and info (for zapLiq) - Added in
mintSynth
confirmation & info (for minting synths thru swap page)
src/views/pages/Swap/SwapPair.js
- Updated APY and dividend logic
src/views/pages/Synths/Overview.js
- Dispatch
getSynthDetails()
&getSynthMinting()
as required - Removed
handleTokenInputChange
- Added
checkValid()
logic to check if a txn is valid and return a label accordingly - Added in
mintSynth
confirmation & info - Added fallback if no synths are deployed
src/views/pages/Vault/Components/DaoDepositModal.js
- Simplified this modal a lot
- Removed the stages and explorer link/loader etc
src/views/pages/Vault/Components/SynthDepositModal.js
- Simplified this modal a lot
- Removed the stages and explorer link/loader etc
src/views/pages/Vault/DaoVault.js
- Siloed out the dispatch calls:
getData()
main call triggers on load & timer now only getdaoGlobalDetails()
&daoMemberDetails()
- New
useEffect
forgetDaoDetails()
&getBondDetails()
which only triggers whenpool.listedPools
updates - New
useEffect
fordaoVaultWeight()
&bondVaultWeight()
which only triggers whenpool.poolDetails
updates - New
useEffect
fordaoDepositTimes()
which only triggers whendao.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
getGlobals()
now only gets thegetSynthGlobalDetails()
on load (and timer)- New
uesEffect
to only getgetSynthDetails()
whensynth.synthArray
updates - New
useEffect()
to only getsynthVaultWeight()
whensynth.synthDetails
updates - Added
isLoading
- Updated all the weight-relevant logic in the JSX
src/views/pages/Vault/SynthVaultItem.js
- Updated
APY()
to use bigNumber where required and return the value - Refactored out
formatDate()
&getFeeBurn()
- Refactored out the math in
getClaimable()
to the relevant math file - Added
checkValid()
helper
Project Information
Official Links
- 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.
- Medium: https://medium.com/spartanprotocol
- Twitter: https://twitter.com/spartanprotocol
- Telegram Community: https://t.me/spartanprotocolorg
- Telegram Announcements: https://t.me/spartanprotocolann
- Community-Built Discord: https://discord.gg/wQggvntnGk