Skip to content

Commit

Permalink
feat: building ownership ref token with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
HinsonSIDAN committed Nov 26, 2023
1 parent 48db192 commit a7dc4af
Show file tree
Hide file tree
Showing 6 changed files with 264 additions and 26 deletions.
16 changes: 15 additions & 1 deletion lib/aiken-content-ownership/common.ak
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,21 @@ pub fn outputs_at_with(
)
}

pub fn onlyMintedToken(
pub fn check_policy_only_burn(mint: MintedValue, policy: PolicyId) -> Bool {
let burn_value = flatten(from_minted_value(mint))
list.all(
burn_value,
fn(x) {
if x.1st == policy {
x.3rd < 0
} else {
True
}
},
)
}

pub fn only_minted_token(
mint: MintedValue,
policy: PolicyId,
name: AssetName,
Expand Down
28 changes: 27 additions & 1 deletion lib/aiken-content-ownership/placeholder.ak
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use aiken/transaction/credential.{
Address, Credential, ScriptCredential, VerificationKeyCredential,
}
use aiken/transaction/value.{PolicyId, add, from_asset, from_lovelace}
use aiken_content_ownership/types.{ContentRegistryDatum, OracleDatum}
use aiken_content_ownership/types.{
ContentRegistryDatum, OracleDatum, OwnershipRegistryDatum,
}
use aiken_content_ownership/utils.{get_registry_token_name}

pub fn mock_policy_id() -> PolicyId {
Expand Down Expand Up @@ -169,3 +171,27 @@ pub fn mock_content_registry_output(
reference_script: None,
}
}

pub fn mock_ownership_registry_datum(
count: Int,
registry: Dict<Int, (ByteArray, ByteArray)>,
) -> OwnershipRegistryDatum {
OwnershipRegistryDatum { count, registry }
}

pub fn mock_ownership_registry_output(
registry_count: Int,
registry_datum: OwnershipRegistryDatum,
) -> Output {
Output {
address: mock_script_address_3(None),
value: from_asset(
mock_policy_id_3(),
get_registry_token_name(registry_count),
1,
)
|> add(#"", #"", 2_000_000),
datum: InlineDatum(registry_datum),
reference_script: None,
}
}
10 changes: 6 additions & 4 deletions validators/content_registry_ref_token.ak
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ use aiken/transaction.{
InlineDatum, Input, Mint, Output, ScriptContext, Transaction, placeholder,
}
use aiken/transaction/value.{PolicyId, add, from_asset, to_minted_value}
use aiken_content_ownership/common.{inputs_with, outputs_at_with, value_length}
use aiken_content_ownership/common.{
check_policy_only_burn, inputs_with, outputs_at_with, value_length,
}
use aiken_content_ownership/placeholder.{
mock_content_registry_datum, mock_content_registry_output, mock_oracle_datum,
mock_oracle_output, mock_policy_id, mock_policy_id_2, mock_policy_id_3,
Expand All @@ -21,9 +23,9 @@ validator(oracle_nft: PolicyId) {
context: ScriptContext,
) -> Bool {
let ScriptContext { purpose, transaction } = context
let Transaction { inputs, outputs, .. } = transaction
let Transaction { inputs, outputs, mint, .. } = transaction
when purpose is {
Mint(_) ->
Mint(current_policy) ->
when (redeemer, inputs_with(inputs, oracle_nft, "")) is {
(RMint, [oracle_input]) -> {
expect InlineDatum(inline_datum) = oracle_input.output.datum
Expand Down Expand Up @@ -68,7 +70,7 @@ validator(oracle_nft: PolicyId) {
_ -> False
}
}
(RBurn, _) -> True
(RBurn, _) -> check_policy_only_burn(mint, current_policy)
_ -> False
}
_ -> False
Expand Down
19 changes: 3 additions & 16 deletions validators/one_time_minting_policy.ak
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ use aiken/list
use aiken/transaction.{
Input, Mint, OutputReference, ScriptContext, Transaction, placeholder,
}
use aiken/transaction/value.{
PolicyId, add, flatten, from_asset, from_minted_value, to_minted_value,
}
use aiken/transaction/value.{PolicyId, add, from_asset, to_minted_value}
use aiken_content_ownership/common.{check_policy_only_burn}
use aiken_content_ownership/placeholder.{
mock_output, mock_policy_id, mock_policy_id_2, mock_utxo_ref,
}
Expand Down Expand Up @@ -32,19 +31,7 @@ validator(utxo_ref: OutputReference) {
None -> False
}
}
RBurn -> {
let burn_value = flatten(from_minted_value(transaction.mint))
list.all(
burn_value,
fn(x) {
if x.1st == current_policy {
x.3rd < 0
} else {
True
}
},
)
}
RBurn -> check_policy_only_burn(transaction.mint, current_policy)
}
_ -> False
}
Expand Down
8 changes: 4 additions & 4 deletions validators/oracle_validator.ak
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use aiken/transaction.{
}
use aiken/transaction/value.{PolicyId, from_asset, to_minted_value}
use aiken_content_ownership/common.{
all_key_signed, key_signed, onlyMintedToken, outputs_at_with,
all_key_signed, key_signed, only_minted_token, outputs_at_with,
}
use aiken_content_ownership/placeholder.{
mock_oracle_datum, mock_oracle_output, mock_policy_id, mock_policy_id_2,
Expand Down Expand Up @@ -40,7 +40,7 @@ validator {
when redeemer is {
CreateContentRegistry ->
// Ref token is minted
onlyMintedToken(
only_minted_token(
mint,
content_registry_ref_token,
get_registry_token_name(content_registry_count),
Expand All @@ -49,7 +49,7 @@ validator {

CreateOwnershipRegistry ->
// Ref token is minted
onlyMintedToken(
only_minted_token(
mint,
ownership_registry_ref_token,
get_registry_token_name(ownership_registry_count),
Expand All @@ -74,7 +74,7 @@ validator {
StopApp ->
// signed by stop key
// oracle nft is burned
key_signed(extra_signatories, stop_key) && onlyMintedToken(
key_signed(extra_signatories, stop_key) && only_minted_token(
mint,
oracle_nft,
"",
Expand Down
209 changes: 209 additions & 0 deletions validators/ownership_registry_ref_token.ak
Original file line number Diff line number Diff line change
@@ -1 +1,210 @@
use aiken/dict
// use aiken/list
use aiken/transaction.{
InlineDatum, Input, Mint, Output, ScriptContext, Transaction, placeholder,
}
use aiken/transaction/value.{PolicyId, add, from_asset, to_minted_value}
use aiken_content_ownership/common.{
check_policy_only_burn, inputs_with, outputs_at_with, value_length,
}
use aiken_content_ownership/placeholder.{
mock_oracle_datum, mock_oracle_output, mock_ownership_registry_datum,
mock_ownership_registry_output, mock_policy_id, mock_policy_id_2,
mock_policy_id_3, mock_utxo_ref,
}
use aiken_content_ownership/types.{
MintPolarity, OracleDatum, OwnershipRegistryDatum, RBurn, RMint,
}
use aiken_content_ownership/utils.{get_registry_token_name}

validator(oracle_nft: PolicyId) {
fn ownership_registry_ref_token(
redeemer: MintPolarity,
context: ScriptContext,
) -> Bool {
let ScriptContext { purpose, transaction } = context
let Transaction { inputs, outputs, mint, .. } = transaction
when purpose is {
Mint(current_policy) ->
when (redeemer, inputs_with(inputs, oracle_nft, "")) is {
(RMint, [oracle_input]) -> {
expect InlineDatum(inline_datum) = oracle_input.output.datum
expect input_datum: OracleDatum = inline_datum
let OracleDatum {
oracle_address,
ownership_registry_ref_token,
ownership_registry_address,
ownership_registry_count,
..
} = input_datum
when
(
outputs_at_with(outputs, oracle_address, oracle_nft, ""),
outputs_at_with(
outputs,
ownership_registry_address,
ownership_registry_ref_token,
get_registry_token_name(ownership_registry_count),
),
)
is {
([oracle_output], [registry_output]) -> {
expect InlineDatum(raw_oracle_datum) = oracle_output.datum
expect InlineDatum(raw_registry_datum) = registry_output.datum
expect oracle_datum: OracleDatum = raw_oracle_datum
expect OwnershipRegistryDatum { count, registry }: OwnershipRegistryDatum =
raw_registry_datum
let oracle_datum_updated =
oracle_datum == OracleDatum {
..input_datum,
ownership_registry_count: ownership_registry_count + 1,
}
let registry_initial_datum_correct =
count == 0 && registry == dict.new()
let oracle_output_value_clean =
value_length(oracle_output.value) == 2
let registry_output_value_clean =
value_length(registry_output.value) == 2
oracle_datum_updated && registry_initial_datum_correct && oracle_output_value_clean && registry_output_value_clean
}
_ -> False
}
}
(RBurn, _) -> check_policy_only_burn(mint, current_policy)
_ -> False
}
_ -> False
}
}
}

type TestCase {
is_oracle_updated: Bool,
is_registry_initialized: Bool,
is_oracle_value_clean: Bool,
is_registry_value_clean: Bool,
}

fn default_test_case() -> TestCase {
TestCase {
is_oracle_updated: True,
is_registry_initialized: True,
is_oracle_value_clean: True,
is_registry_value_clean: True,
}
}

fn make_mock_tx_body(record_count: Int, test_case: TestCase) -> Transaction {
let registry_token_value =
from_asset(mock_policy_id_3(), get_registry_token_name(record_count), 1)
let TestCase {
is_oracle_updated,
is_registry_initialized,
is_oracle_value_clean,
is_registry_value_clean,
} = test_case
let new_count =
if is_oracle_updated {
record_count + 1
} else {
record_count
}
let new_registry =
if is_registry_initialized {
mock_ownership_registry_datum(0, dict.new())
} else {
mock_ownership_registry_datum(1, dict.new())
}
let oracle_value =
if is_oracle_value_clean {
from_asset(mock_policy_id(), "", 1) |> add(#"", #"", 2_000_000)
} else {
from_asset(mock_policy_id(), "", 1)
|> add(#"", #"", 2_000_000)
|> add(mock_policy_id_2(), "123", 1)
}
let registry_value =
if is_registry_value_clean {
registry_token_value |> add(#"", #"", 2_000_000)
} else {
registry_token_value
|> add(#"", #"", 2_000_000)
|> add(mock_policy_id_2(), "123", 1)
}
Transaction {
..placeholder(),
mint: to_minted_value(registry_token_value),
inputs: [
Input {
output_reference: mock_utxo_ref(1),
output: mock_oracle_output(mock_oracle_datum()),
},
],
outputs: [
Output {
..mock_oracle_output(
OracleDatum {
..mock_oracle_datum(),
ownership_registry_count: new_count,
},
),
value: oracle_value,
},
Output {
..mock_ownership_registry_output(record_count, new_registry),
value: registry_value,
},
],
}
}

test success_mint() {
let redeemer = RMint
let tx = make_mock_tx_body(0, default_test_case())
let ctx = ScriptContext { purpose: Mint(mock_policy_id_3()), transaction: tx }
ownership_registry_ref_token(mock_policy_id(), redeemer, ctx)
}

test fail_mint_without_update_oracle() {
let redeemer = RMint
let tx =
make_mock_tx_body(
0,
TestCase { ..default_test_case(), is_oracle_updated: False },
)
let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx }
!ownership_registry_ref_token(mock_policy_id(), redeemer, ctx)
}

test fail_mint_without_registry_initialized() {
let redeemer = RMint
let tx =
make_mock_tx_body(
0,
TestCase { ..default_test_case(), is_registry_initialized: False },
)
let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx }
!ownership_registry_ref_token(mock_policy_id(), redeemer, ctx)
}

test fail_mint_with_unclean_oracle_value() {
let redeemer = RMint
let tx =
make_mock_tx_body(
0,
TestCase { ..default_test_case(), is_oracle_value_clean: False },
)
let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx }
!ownership_registry_ref_token(mock_policy_id(), redeemer, ctx)
}

test fail_mint_with_unclean_registry_value() {
let redeemer = RMint
let tx =
make_mock_tx_body(
0,
TestCase { ..default_test_case(), is_registry_value_clean: False },
)
let ctx = ScriptContext { purpose: Mint(mock_policy_id()), transaction: tx }
!ownership_registry_ref_token(mock_policy_id(), redeemer, ctx)
}

0 comments on commit a7dc4af

Please sign in to comment.