Sagres-waves v0.1 release: open source vesting smart contracts generator for WAVES blockchain

in utopian-io •  3 months ago

I'm releasing Sagres-waves v0.1, an open source web app for generation of vesting smart contracts for WAVES blockchain.

Sagres generator is live at sagres-waves.com

It can be used to define shmaht contracts for linear vesting schemes with max vesting period and vesting cliff at the start. Smart contract restricts withdrawal of predefined asset for individual WAVES accounts of project founders, investors, employees and consultants. An individual smart contract should be deployed for every account that needs vesting scheme.

Code and links

Sagres Github repo

Sagres website

Sagres 0.1 commits

Waves blockchain

RIDE smart contract language documentation

Sagres?

Sagres is a beautiful place in Portugal, where steep cliffs are shaped and eroded by waves. I find Sagres to be a fitting name for vesting contracts for WAVES blockchain.

Why?

Vesting is an important incentive design tool that can be used to align incentives of project co-founders, employees, consultants and investors.

Features

Sagres includes a vesting smart contract template that accepts a set of parameters and generates a RIDE smart contract that is designed to be attached to individual accounts of token holders.

ParameterDescription
startingUnixTimestampMsecA starting date for vesting period
originalAssetAmountA starting amount of tokens for the given account
assetIdasset ID
ownerPkaccount owner Public Key
maxVestingPeriodWeeksvesting period in weeks
cliffPeriodWeekscliff period in weeks

Smart contract template

  let startingUnixTimestampMsec = ${startingUnixTimestampMsec} 
  let originalAssetAmount = ${originalAssetAmount} 
  let assetId = base58'${assetId}'
  let ownerPk = base58'${ownerPk}'
  
  match tx {
    case tx:TransferTransaction =>
    
      let txSenderIsOwner = ownerPk == tx.senderPk
      let txSenderAddress = addressFromPublicKey(tx.senderPk)
    
    
      let elapsedMsec = tx.timestamp - startingUnixTimestampMsec
      let elapsedWeeks = elapsedMsec / 7 * 86400 * 1000 
      let vestingPeriodEnded = if elapsedWeeks > ${maxVestingPeriodWeeks} then true else false
      
      let currentBalance = assetBalance(txSenderAddress, assetId)
      let remainingBalanceAfterTx = currentBalance - tx.amount
  
      let minRequiredAtTxTimestamp = if elapsedWeeks <= ${cliffPeriodWeeks} then originalAssetAmount
          else originalAssetAmount * (${maxVestingPeriodWeeks} - elapsedWeeks / ${maxVestingPeriodWeeks} - ${cliffPeriodWeeks})
  
      let vestingConditionsMatch = remainingBalanceAfterTx >= minRequiredAtTxTimestamp
  
      sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPk) && txSenderIsOwner && (vestingPeriodEnded || vestingConditionsMatch)
  
    case burnTx:BurnTransaction => true
    case _ => false
  }

Example of generated smart contract

  let startingUnixTimestampMsec = 1532214000000 
  let originalAssetAmount = 10000 
  let assetId = base58'EAhaYpFg9a3833aTgAxBBfLEKhP8yZkZ9qZpXDjBXUCg'
  let ownerPk = base58'774ecw4Sk1tbqXS8RVvCorVEdW8ihmdysponYjfFHnm7'
  
  match tx {
    case tx:TransferTransaction =>
    
      let txSenderIsOwner = ownerPk == tx.senderPk
      let txSenderAddress = addressFromPublicKey(tx.senderPk)
    
    
      let elapsedMsec = tx.timestamp - startingUnixTimestampMsec
      let elapsedWeeks = elapsedMsec / 7 * 86400 * 1000 
      let vestingPeriodEnded = if elapsedWeeks > 12 then true else false
      
      let currentBalance = assetBalance(txSenderAddress, assetId)
      let remainingBalanceAfterTx = currentBalance - tx.amount
  
      let minRequiredAtTxTimestamp = if elapsedWeeks <= 6 then originalAssetAmount
          else originalAssetAmount * (12 - elapsedWeeks / 12 - 6)
  
      let vestingConditionsMatch = remainingBalanceAfterTx >= minRequiredAtTxTimestamp
  
      sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPk) && txSenderIsOwner && (vestingPeriodEnded || vestingConditionsMatch)
  
    case burnTx:BurnTransaction => true
    case _ => false
  }

( ◔ ౪◔)⊃━☆゚.*・

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Thank you for your contribution. I can see you have exposed Test Private and Public Key publicly, it's better not to do it.

For this inner if statement https://github.com/ontofractal/sagres_waves/blob/master/src/registerServiceWorker.js#L63, can it not be done in one if using AND operator.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

good info

Hey @ontofractal
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!