I want to share with you a glimpse of the new contract development workflow that we’ve been working on for some time. The idea is to provide the following abilities to the contract developers:
1. Write a contract in Scala subset(ErgoScala) Here is a buyer’s contract from assets atomic exchange example:
def buyer(ctx: Context,
deadline: Int,
tokenId: Coll[Byte],
tokenAmount: Long,
pkA: SigmaProp): SigmaProp = {
import ctx._
(HEIGHT > deadline && pkA) ||
{
val tokens = OUTPUTS(0).tokens
val tokenDataCorrect = tokens.nonEmpty &&
tokens(0)._1 == tokenId &&
tokens(0)._2 >= tokenAmount
val knownId = OUTPUTS(0).R4[Coll[Byte]].get == SELF.id
tokenDataCorrect &&
OUTPUTS(0).propositionBytes == pkA.propBytes &&
knownId
}
}
2. Prove it’s properties (formal verification) using Stainless.
Here are three proven properties of the buyer
contract proofs
3. Compile the contract to ErgoTree and executable Scala func. With the following call:
def buyerContractInstance(deadline: Int,
tokenId: Coll[Byte],
tokenAmount: Long,
pkA: SigmaProp): ErgoContract =
ErgoContractCompiler.compile { context: Context =>
buyer(context: Context, deadline: Int, tokenId: Coll[Byte], tokenAmount: Long, pkA: SigmaProp)
}
val ergoContract = buyerContractInstance(10000, Coll[Byte](...), 100, SigmaProp.fromBytes(...))
ergoContract.tree
gives you ErgoTree of the buyer
contract instance with passed parameters inlined. You can serialize it to bytes and use in a box.
ergoContract.scalaFunc
gives you a function with signature Context => SigmaProp
with compiled buyer
contract instance where passed parameters are inlined. You can call it in tests passing any suitable context (height, in and out boxes, etc.).
And all this is available inside your favorite Scala IDE.
4. Use compiled contracts and ErgoTrees from Appkit The ergoContract variable can be made available in an application written using Appkit. To achieve that the module with verified contracts should be added to Appkit application as a dependency. Then instead of writing
.contract(ctx.compileContract(
ConstantsBuilder.create()
.item("deadline", 1000)
.item("tokenId", Coll[Byte](...))
.item("tokenAmount", 100)
.item("pkA", SigmaProp.fromBytes(...))
.build(),
"{ body of the contract }"))
You can write something like
.contract(ergoContract.ergoTree(10000, Coll[Byte](...), 100, SigmaProp.fromBytes(...)))