Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

18 implement asteria validator checks #28

Merged
merged 3 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions onchain/docs/mvp-design/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,17 @@ Pays the min ada locked in the `ShipState` UTxO back to the ship owner and burns
## Validators & Minting Policies

### Asteria validator:
* Params: `AdminToken`.
* Params: `AdminToken`, `SHIP_MINT_FEE` and `MAX_ASTERIA_MINING`.

#### *AddNewShip Redeemer*
* `AsteriaUTxO` output value equals input value plus the `SHIP_MINT_FEE`.
* `AdminToken` is in the input.
* datum doesn't change.
* datum `ship_counter` field is incremented by 1.

#### *Mine Redeemer*
* `ShipToken` is present in some input.
* `AsteriaUTxO` output value has at most `MAX_ASTERIA_MINING`% adas less than input value.
* datum doesn't change.

### Pellet validator:
* Params: `AdminToken`.
Expand Down
36 changes: 18 additions & 18 deletions onchain/src/plutus.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,39 @@
{
"title": "asteria.spend",
"datum": {
"title": "_datum",
"title": "datum",
"schema": {
"$ref": "#/definitions/asteria~1types~1AsteriaDatum"
}
},
"redeemer": {
"title": "_redeemer",
"title": "redeemer",
"schema": {
"$ref": "#/definitions/asteria~1types~1AsteriaRedeemer"
}
},
"parameters": [
{
"title": "_admin_token",
"title": "admin_token",
"schema": {
"$ref": "#/definitions/Tuple$ByteArray_ByteArray"
"$ref": "#/definitions/asteria~1types~1AssetClass"
}
},
{
"title": "ship_mint_lovelace_fee",
"schema": {
"$ref": "#/definitions/Int"
}
},
{
"title": "max_asteria_mining",
"schema": {
"$ref": "#/definitions/Int"
}
}
],
"compiledCode": "5898010000323232323232232232232253330084a229309b2b19299980399b874800000454ccc028c024dd50010a4c2c2a66600e66e1d20020011533300a300937540042930b0b18039baa00153330043370e900018029baa001132323232533300b300d002149858dd7180580098058011bad3009001300637540022c6466ec0c01c004c01cc020004dd6000ab9a5573aaae7955cfaba157441",
"hash": "27cbc8819bede902bc58445bb6fc3d8c91341d0f48f58b5ea7adb72e"
"compiledCode": "5907040100003232323232323222322322323232232322533300e32323232323232325333016300b3017375400e26464646464a66603c60420042646464a6660426048004264a66603e66e1d20043020375400226464646464a666048603a604a6ea80684c8c8c94ccc09ccdc4240006660086eacc030c0a4dd5180618149baa00d375c602060526ea8098dd7180618149baa0261533302700315333027002100114a0294052819b8f375c601660506ea801c044cdc39bad300e3027375400c66e0004520023375e6012604c6ea801cdd319912999813180f8118800899191980080080191299981600089981699bb04c1014000374c00697adef6c60132323232533302d3375e66012911000024c103d879800013303133760981014000374c00e00a2a66605a66e3d22100002132533302e3027302f375400226606466ec1301014000303330303754002008200864a66605ca66606200229445280a6103d87a80001300d33032374c00297ae03233001001002225333032001133033337609801014000375005897adef6c6013232323253330333375e6601e911000024c103d879800013303733760981014000375006000a2a66606666e3d221000021325333034302d3035375400226607066ec1301014000303930363754002008200864a666068605a002298103d87a80001301333038375000297ae03370000206026606e66ec0dd48011ba800133006006003375a60680066eb8c0c8008c0d8008c0d00044cc0c4cdd81ba9002374c0026600c00c0066eacc0b800cdd7181600118180011817000991900119198008008011129998160008a4c264a66605a002293099192999816181298169baa33008375c605a60620086eb8c0b40084cc014014cc0c000800458c0c4008c0bc004c0bc004cc0a8cdd8261014000375004697adef6c60225333026337200040022980103d8798000153330263371e0040022980103d87a800014c103d87b800037566012604c6ea8c024c098dd50050a999812180e98129baa323300100101422533302900114c0103d87a80001323253330283232330010013300200232533302b3020302c3754002297adef6c60137566060605a6ea8004cc020dd5980798161baa300f302c375400802a44a66605c00229404c94ccc0b0cdc7999b8c48000dc6a45045348495000375c606200491104534849500014a2266006006002606200244a66605a002297ae013302e302b302f001330020023030001130073302c0024bd70099802002000981680118158008992999812980f18131baa0011323253330273232323371266e08dd698178009bad302f3030002337046eb4c0bc008dd69817981800098159baa3232300a3302f375066e08dd698180011bad30300013302f375066e08dd6981818188011bad303030310014bd7018161baa32323232300d33032375066e04cdc11bad3033004001337046eb4c0cc00800ccc0c8dd419b820030014bd701bad30323033001302e37546062605c6ea8020dd69818181880098161baa300348008c0acdd5180118021bab300e302b3754601c60566ea803cc0a8dd5180098019bab300d302a37540164600e660586ea0004cc0b130010101004bd7008008a503375e04000e4666006002910100488100165333024301d4832004530103d87a80001533302433710906400a400026006660506006660506ea0cdc0a400003e660506ea0cdc024000906380a5eb812f5c026006660506006660506ea007ccc0a1301021864004bd7025eb8058888c94ccc09cc070c0a0dd50008a400026eb4c0b0c0a4dd5000992999813980e18141baa00114c103d87a8000132330010013756605a60546ea8008894ccc0b0004530103d87a80001323232533302c3371e00e6eb8c0b400c4c02ccc0c0dd4000a5eb804cc014014008dd6981680118180011817000998020018011119198008008019129998148008a60103d87a8000132323253330293371e00c6eb8c0a800c4c020cc0b4dd3000a5eb804cc014014008dd59815001181680118158009ba548000c060004c090c084dd50008b18119812181218101baa0011630220013300400a23375e600c603e6ea8004c018c07cdd51801180f9baa00323021302200116301f0013300100823375e600660386ea800401088c8cc00400400c894ccc07c00452f5c026464a66603c600a00426604400466008008002266008008002604600460420024603a002603660306ea801c58dd7180d180d8011bad30190013015375401a6eb0c05cc060c060008dd6180b00098091baa3015002301430150013010375400229309b2b19299980698030008a99980818079baa00314985854ccc034c00800454ccc040c03cdd50018a4c2c2c601a6ea8008dc3a400460020064a666012600460146ea80044c8c8c8c94ccc040c04c00852616375c602200260220046eb4c03c004c02cdd50008b1b8748000dd68009bad0015734aae7555cf2ab9f5740ae855d11",
"hash": "3a75534efcf27b51da03e46d531facefc6cb531c69c9aee02419faec"
},
{
"title": "pellet.spend",
Expand Down Expand Up @@ -184,18 +196,6 @@
}
]
},
"Tuple$ByteArray_ByteArray": {
"title": "Tuple",
"dataType": "list",
"items": [
{
"$ref": "#/definitions/ByteArray"
},
{
"$ref": "#/definitions/ByteArray"
}
]
},
"aiken/transaction/credential/Address": {
"title": "Address",
"description": "A Cardano `Address` typically holding one or two credential references.\n\n Note that legacy bootstrap addresses (a.k.a. 'Byron addresses') are\n completely excluded from Plutus contexts. Thus, from an on-chain\n perspective only exists addresses of type 00, 01, ..., 07 as detailed\n in [CIP-0019 :: Shelley Addresses](https://github.com/cardano-foundation/CIPs/tree/master/CIP-0019/#shelley-addresses).",
Expand Down
89 changes: 80 additions & 9 deletions onchain/src/validators/asteria.ak
Original file line number Diff line number Diff line change
@@ -1,13 +1,84 @@
use aiken/transaction.{ScriptContext}
use aiken/transaction/value.{AssetName, PolicyId}
use asteria/types.{AsteriaDatum, AsteriaRedeemer}
use aiken/list
use aiken/math/rational.{compare_with, from_int}
use aiken/transaction.{InlineDatum, ScriptContext, Spend, Transaction}
use aiken/transaction/value.{ada_asset_name, ada_policy_id}
use asteria/types.{AddNewShip, AssetClass, AsteriaDatum, AsteriaRedeemer, Mine}
use asteria/utils

validator(_admin_token: (PolicyId, AssetName)) {
fn spend(
_datum: AsteriaDatum,
_redeemer: AsteriaRedeemer,
_ctx: ScriptContext,
validator(
admin_token: AssetClass,
ship_mint_lovelace_fee: Int,
max_asteria_mining: Int,
) {
pub fn spend(
datum: AsteriaDatum,
redeemer: AsteriaRedeemer,
ctx: ScriptContext,
) -> Bool {
True
let ScriptContext { transaction, purpose } = ctx
let Transaction { inputs, outputs, .. } = transaction
let AsteriaDatum { ship_counter, shipyard_policy } = datum
expect Spend(asteria_ref) = purpose
expect [asteria_input] =
list.filter(inputs, fn(input) { input.output_reference == asteria_ref })
expect [asteria_output] =
list.filter(
outputs,
fn(output) { output.address == asteria_input.output.address },
)
expect InlineDatum(asteria_output_datum) = asteria_output.datum
expect asteria_output_datum: AsteriaDatum = asteria_output_datum
when redeemer is {
AddNewShip -> {
let must_hold_admin_token =
value.quantity_of(
asteria_input.output.value,
admin_token.policy,
admin_token.name,
) > 0
let must_add_fee =
asteria_output.value == (
asteria_input.output.value
|> value.add(ada_policy_id, ada_asset_name, ship_mint_lovelace_fee)
)
let must_increment_counter =
asteria_output_datum.ship_counter == ship_counter + 1
let must_preserve_shipyard_policy =
asteria_output_datum.shipyard_policy == shipyard_policy

and {
must_hold_admin_token,
must_add_fee,
must_increment_counter,
must_preserve_shipyard_policy,
}
}

Mine -> {
expect Some(_) =
list.find(
inputs,
fn(input) {
utils.is_ship_token_in_utxo(input.output, shipyard_policy)
},
)
expect Some(percentage) = rational.new(max_asteria_mining, 100)
let rewards = value.lovelace_of(asteria_input.output.value)
let must_respect_max_mining =
compare_with(
from_int(value.lovelace_of(asteria_output.value)),
>=,
rational.mul(
from_int(rewards),
rational.sub(from_int(1), percentage),
),
)
let must_preserve_datum = datum == asteria_output_datum
and {
must_respect_max_mining,
must_preserve_datum,
}
}
}
}
}
Loading
Loading