Skip to content

Commit

Permalink
onchain for consuming Asteria & pellets
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscojoray committed Apr 25, 2024
1 parent d5b4006 commit 159f6c4
Show file tree
Hide file tree
Showing 9 changed files with 455 additions and 51 deletions.
2 changes: 2 additions & 0 deletions onchain/src/lib/asteria/test_mock.ak
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub const asteria_credential = #"2222"

pub const pilot_credential = #"3333"

pub const admin_credential = #"4444"

pub const ship_token_name = "SHIP7"

pub const pilot_token_name = "PILOT7"
2 changes: 2 additions & 0 deletions onchain/src/lib/asteria/types.ak
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub type PelletDatum {

pub type PelletRedeemer {
Provide { amount: Int }
ConsumePellet
}

pub type AsteriaDatum {
Expand All @@ -44,6 +45,7 @@ pub type AsteriaDatum {
pub type AsteriaRedeemer {
AddNewShip
Mine
ConsumeAsteria
}

pub type ShipyardRedeemer {
Expand Down
10 changes: 10 additions & 0 deletions onchain/src/lib/asteria/utils.ak
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use aiken/dict.{keys}
use aiken/list.{any}
use aiken/math
use aiken/transaction.{Output}
use aiken/transaction/credential.{
Address, ScriptCredential, VerificationKeyCredential,
}
use aiken/transaction/value.{AssetName, PolicyId, tokens}

pub fn is_ship_token_in_utxo(utxo: Output, shipyard_policy: PolicyId) -> Bool {
Expand Down Expand Up @@ -30,3 +33,10 @@ pub fn distance(delta_x: Int, delta_y: Int) -> Int {
pub fn required_fuel(distance: Int, fuel_per_step: Int) -> Int {
distance * fuel_per_step
}

pub fn is_wallet_address(address: Address) -> Bool {
when address.payment_credential is {
VerificationKeyCredential(_) -> True
ScriptCredential(_) -> False
}
}
28 changes: 20 additions & 8 deletions onchain/src/plutus.json

Large diffs are not rendered by default.

44 changes: 36 additions & 8 deletions onchain/src/validators/asteria.ak
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use aiken/list
use aiken/math/rational.{compare_with, from_int}
use aiken/option
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/types.{
AddNewShip, AssetClass, AsteriaDatum, AsteriaRedeemer, ConsumeAsteria, Mine,
}
use asteria/utils

validator(
Expand All @@ -21,15 +24,17 @@ validator(
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 -> {
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

let must_hold_admin_token =
value.quantity_of(
asteria_input.output.value,
Expand All @@ -55,6 +60,14 @@ validator(
}

Mine -> {
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

expect Some(_) =
list.find(
inputs,
Expand All @@ -81,6 +94,21 @@ validator(
must_preserve_datum?,
}
}

ConsumeAsteria -> {
let admin_token_input =
list.find(
inputs,
fn(input) {
utils.is_wallet_address(input.output.address) && value.quantity_of(
input.output.value,
admin_token.policy,
admin_token.name,
) > 0
},
)
option.is_some(admin_token_input)?
}
}
}
}
82 changes: 56 additions & 26 deletions onchain/src/validators/pellet.ak
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use aiken/list.{filter}
use aiken/option
use aiken/transaction.{InlineDatum, Output, ScriptContext, Spend, Transaction}
use aiken/transaction/value.{quantity_of}
use asteria/types.{AssetClass, PelletDatum, PelletRedeemer, Provide}
use asteria/types.{
AssetClass, ConsumePellet, PelletDatum, PelletRedeemer, Provide,
}
use asteria/utils

validator(admin_token: AssetClass) {
Expand All @@ -10,37 +13,64 @@ validator(admin_token: AssetClass) {
redeemer: PelletRedeemer,
ctx: ScriptContext,
) -> Bool {
let Provide(amount) = redeemer
let PelletDatum { fuel, shipyard_policy, .. } = datum
let ScriptContext { transaction, purpose } = ctx
let Transaction { inputs, outputs, .. } = transaction
when redeemer is {
Provide(amount) -> {
let PelletDatum { fuel, shipyard_policy, .. } = datum

expect Spend(utxo_ref) = purpose
expect [own_input] =
list.filter(inputs, fn(input) { input.output_reference == utxo_ref })
expect [own_output] =
filter(
outputs,
fn(output) { output.address == own_input.output.address },
)
expect InlineDatum(out_datum) = own_output.datum
expect out_datum: PelletDatum = out_datum

expect Spend(utxo_ref) = purpose
expect [own_input] =
list.filter(inputs, fn(input) { input.output_reference == utxo_ref })
expect [own_output] =
filter(outputs, fn(output) { output.address == own_input.output.address })
expect InlineDatum(out_datum) = own_output.datum
expect out_datum: PelletDatum = out_datum
expect Some(_) =
list.find(
inputs,
fn(input) {
utils.is_ship_token_in_utxo(input.output, shipyard_policy)
},
)

expect Some(_) =
list.find(
inputs,
fn(input) { utils.is_ship_token_in_utxo(input.output, shipyard_policy) },
)
let has_enough_fuel = amount <= fuel
let own_input_has_admin_token =
quantity_of(
own_input.output.value,
admin_token.policy,
admin_token.name,
) == 1
let value_not_changed = own_input.output.value == own_output.value
let datum_update_ok =
out_datum == PelletDatum { ..datum, fuel: fuel - amount }

let has_enough_fuel = amount <= fuel
let own_input_has_admin_token =
quantity_of(own_input.output.value, admin_token.policy, admin_token.name) == 1
let value_not_changed = own_input.output.value == own_output.value
let datum_update_ok =
out_datum == PelletDatum { ..datum, fuel: fuel - amount }
and {
has_enough_fuel?,
datum_update_ok?,
value_not_changed?,
own_input_has_admin_token?,
}
}

and {
has_enough_fuel?,
datum_update_ok?,
value_not_changed?,
own_input_has_admin_token?,
ConsumePellet -> {
let admin_token_input =
list.find(
inputs,
fn(input) {
utils.is_wallet_address(input.output.address) && value.quantity_of(
input.output.value,
admin_token.policy,
admin_token.name,
) > 0
},
)
option.is_some(admin_token_input)?
}
}
}
}
5 changes: 3 additions & 2 deletions onchain/src/validators/spacetime.ak
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use aiken/bytearray
use aiken/dict
use aiken/list
use aiken/option
use aiken/string
use aiken/transaction.{InlineDatum, Mint, ScriptContext, Spend, Transaction}
use aiken/transaction/credential.{
Expand Down Expand Up @@ -230,13 +231,13 @@ validator(
}

BurnShip -> {
expect Some(_) =
let ship_input =
list.find(
inputs,
fn(input) { utils.is_ship_token_in_utxo(input.output, policy_id) },
)
expect [(_, -1)] = minted_tokens
True
option.is_some(ship_input)
}
}
}
Expand Down

0 comments on commit 159f6c4

Please sign in to comment.