Skip to content

Commit

Permalink
feat: add most logics
Browse files Browse the repository at this point in the history
  • Loading branch information
HinsonSIDAN committed Jul 25, 2024
1 parent 4c01b2a commit 53192cc
Show file tree
Hide file tree
Showing 30 changed files with 749 additions and 314 deletions.
68 changes: 53 additions & 15 deletions lib/aiken-virtual-dex/placeholder.ak
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use aiken/hash.{blake2b_256}
use aiken/transaction.{InlineDatum, Input, NoDatum, Output}
use aiken/transaction/value.{PolicyId, Value, add, from_asset}
use aiken_virtual_dex/types.{
AccountNormalDatum, EmergencyUnlockPhase1, EmergencyUnlockPhase2, OracleDatum,
VirtualDexDatum,
AccountNormalDatum, AccountOracleDatum, DexOracleDatum, EmergencyUnlockPhase1,
EmergencyUnlockPhase2, VirtualDexDatum,
}
use aiken_virtual_dex/utils.{get_emergency_token_name}
use sidan_placeholder/address.{mock_pub_key_address, mock_script_address}
Expand All @@ -14,14 +14,22 @@ use sidan_placeholder/key_hex.{
use sidan_placeholder/output_reference.{mock_utxo_ref}

// Smart contract specific placeholders
pub fn mock_oracle_policy_id() -> PolicyId {
pub fn mock_account_oracle_policy_id() -> PolicyId {
mock_policy_id(0)
}

pub fn mock_oracle_address() {
pub fn mock_dex_oracle_policy_id() -> PolicyId {
mock_policy_id(3)
}

pub fn mock_account_oracle_address() {
mock_script_address(1, None)
}

pub fn mock_dex_oracle_address() {
mock_script_address(6, None)
}

pub fn mock_fee_ref_token() {
mock_policy_id(1)
}
Expand Down Expand Up @@ -58,29 +66,56 @@ pub fn mock_token_asset_class() {
(mock_policy_id(4), "A potentially very long name")
}

pub fn mock_oracle_datum() {
OracleDatum {
oracle_nft: mock_oracle_policy_id(),
oracle_address: mock_oracle_address(),
pub fn mock_account_oracle_datum() {
AccountOracleDatum {
oracle_nft: mock_account_oracle_policy_id(),
oracle_address: mock_account_oracle_address(),
operation_key: mock_operation_key(),
stop_key: mock_stop_key(),
}
}

pub fn mock_oracle_output(oracle_datum: OracleDatum) -> Output {
pub fn mock_account_oracle_output(oracle_datum: AccountOracleDatum) -> Output {
Output {
address: mock_oracle_address(),
value: from_asset(mock_oracle_policy_id(), "", 1)
address: mock_account_oracle_address(),
value: from_asset(mock_account_oracle_policy_id(), "", 1)
|> add(#"", #"", 2_000_000),
datum: InlineDatum(oracle_datum),
reference_script: None,
}
}

pub fn mock_oracle_ref_input() -> Input {
pub fn mock_account_oracle_ref_input() -> Input {
Input {
output_reference: mock_utxo_ref(0, 0),
output: mock_oracle_output(mock_oracle_datum()),
output: mock_account_oracle_output(mock_account_oracle_datum()),
}
}

pub fn mock_dex_oracle_datum() {
DexOracleDatum {
oracle_nft: mock_dex_oracle_policy_id(),
oracle_address: mock_dex_oracle_address(),
dex_address: mock_virtual_dex_address(),
operation_key: mock_operation_key(),
stop_key: mock_stop_key(),
}
}

pub fn mock_dex_oracle_output(oracle_datum: DexOracleDatum) -> Output {
Output {
address: mock_dex_oracle_address(),
value: from_asset(mock_dex_oracle_policy_id(), "", 1)
|> add(#"", #"", 2_000_000),
datum: InlineDatum(oracle_datum),
reference_script: None,
}
}

pub fn mock_dex_oracle_ref_input() -> Input {
Input {
output_reference: mock_utxo_ref(1, 0),
output: mock_dex_oracle_output(mock_dex_oracle_datum()),
}
}

Expand Down Expand Up @@ -126,6 +161,7 @@ pub fn mock_buy_ada_order_input(
list_price_times_1mil: Int,
lot_size: Int,
extra_lovelace: Int,
fee_lovelace: Int,
) {
Input {
output_reference: mock_utxo_ref(0, 50 + variation),
Expand All @@ -135,7 +171,8 @@ pub fn mock_buy_ada_order_input(
mock_token_asset_class().1st,
mock_token_asset_class().2nd,
lot_size,
),
)
|> add("", "", extra_lovelace + fee_lovelace),
datum: InlineDatum(
VirtualDexDatum {
account_address: mock_account_address(),
Expand All @@ -155,12 +192,13 @@ pub fn mock_sell_ada_order_input(
list_price_times_1mil: Int,
lot_size: Int,
extra_lovelace: Int,
fee_lovelace: Int,
) {
Input {
output_reference: mock_utxo_ref(0, 60 + variation),
output: Output {
address: mock_virtual_dex_address(),
value: from_asset("", "", lot_size),
value: from_asset("", "", lot_size + extra_lovelace + fee_lovelace),
datum: InlineDatum(
VirtualDexDatum {
account_address: mock_account_address(),
Expand Down
37 changes: 26 additions & 11 deletions lib/aiken-virtual-dex/types.ak
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,25 @@ pub type MintPolarity {
RBurn
}

// 2. OracleValidator
pub type OracleDatum {
// 2. EmergencyToken
pub type EmergencyTokenMintingPolarity {
EMint { current_timestamp: Int, account_address: Address }
EBurn
}

// 3. AccountOracle
pub type AccountOracleDatum {
oracle_nft: PolicyId,
oracle_address: Address,
operation_key: ByteArray,
stop_key: ByteArray,
}

pub type OracleRedeemer {
pub type AccountOracleRedeemer {
RotateKey { new_operation_key: ByteArray, new_stop_key: ByteArray }
StopApp
}

// 3. EmergencyToken
pub type EmergencyTokenMintingPolarity {
EMint { current_timestamp: Int, account_address: Address }
EBurn
}

// 3. Account
pub type AccountRedeemer {
AccountUserUnlock
Expand All @@ -41,7 +41,7 @@ pub type AccountDatum {
EmergencyUnlockPhase2 { valid_since: Int, minter: ByteArray }
}

pub type AccountEmergencyActionPhase1Redeemer {
pub type AccountEmergencyPhase1Redeemer {
owner: ByteArray,
own_input: Input,
initiate_before: Int,
Expand All @@ -53,7 +53,22 @@ pub type AccountEmergencyActionPhase2Redeemer {
withdraw_output: OutputReference,
}

// 5. VirtualDex
// 5. DexOracle

pub type DexOracleDatum {
oracle_nft: PolicyId,
oracle_address: Address,
dex_address: Address,
operation_key: ByteArray,
stop_key: ByteArray,
}

pub type DexOracleRedeemer {
DexRotateKey { new_operation_key: ByteArray, new_stop_key: ByteArray }
StopDex
}

// 6. VirtualDex
pub type VirtualDexDatum {
account_address: Address,
is_long: Bool,
Expand Down
42 changes: 28 additions & 14 deletions lib/aiken-virtual-dex/validators/account/account.ak
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use aiken/hash.{Blake2b_224, Hash}
use aiken/pairs
use aiken/transaction.{ScriptContext, Spend, Transaction, find_input}
use aiken/transaction/credential.{Inline, Script, ScriptCredential}
use aiken_virtual_dex/types.{
AccountAppUnlock, AccountDatum, AccountEmergencyActionPhase1Redeemer,
AccountEmergencyActionPhase2Redeemer, AccountEmergencyUnlockPhase1,
AccountAppUnlock, AccountDatum, AccountEmergencyActionPhase2Redeemer,
AccountEmergencyPhase1Redeemer, AccountEmergencyUnlockPhase1,
AccountEmergencyUnlockPhase2, AccountRedeemer, AccountUserUnlock,
}
use sidan_utils/redeemers.{withdrawal_redeemer}
Expand All @@ -19,29 +20,42 @@ pub fn account_logic(
context: ScriptContext,
) -> Bool {
let ScriptContext { transaction, purpose } = context
when transaction.withdrawals is {
[Pair(stake_cred, _)] -> {
expect Inline(ScriptCredential(stake_script_hash)) = stake_cred
when redeemer is {
AccountUserUnlock -> stake_script_hash == user_unlock
AccountAppUnlock -> stake_script_hash == app_unlock
AccountEmergencyUnlockPhase1 -> {
when redeemer is {
AccountUserUnlock ->
pairs.has_key(
transaction.withdrawals,
Inline(ScriptCredential(user_unlock)),
)
AccountAppUnlock ->
pairs.has_key(
transaction.withdrawals,
Inline(ScriptCredential(app_unlock)),
)
AccountEmergencyUnlockPhase1 ->
when transaction.withdrawals is {
[Pair(stake_cred, _)] -> {
expect Inline(ScriptCredential(stake_script_hash)) = stake_cred
expect Spend(own_utxo) = purpose
expect Some(own_input) = find_input(transaction.inputs, own_utxo)
expect Some(withdrawal_script_redeemer) =
transaction.redeemers |> withdrawal_redeemer(stake_script_hash)
expect AccountEmergencyActionPhase1Redeemer {
expect AccountEmergencyPhase1Redeemer {
owner: redeemer_owner,
own_input: redeemer_own_input,
..
}: AccountEmergencyActionPhase1Redeemer = withdrawal_script_redeemer
}: AccountEmergencyPhase1Redeemer = withdrawal_script_redeemer
let is_withdrawal_redeemer_correct =
redeemer_owner == owner && redeemer_own_input == own_input
let is_withdrawal_script_present =
stake_script_hash == emergency_unlock_phase1
is_withdrawal_redeemer_correct && is_withdrawal_script_present
}
AccountEmergencyUnlockPhase2 -> {
_ -> False
}
AccountEmergencyUnlockPhase2 ->
when transaction.withdrawals is {
[Pair(stake_cred, _)] -> {
expect Inline(ScriptCredential(stake_script_hash)) = stake_cred
expect Spend(own_utxo) = purpose
expect Some(own_input) = find_input(transaction.inputs, own_utxo)
expect Some(withdrawal_script_redeemer) =
Expand All @@ -57,8 +71,8 @@ pub fn account_logic(
stake_script_hash == emergency_unlock_phase2
is_withdrawal_redeemer_correct && is_withdrawal_script_present
}

_ -> False
}
}
_ -> False
}
}
4 changes: 2 additions & 2 deletions lib/aiken-virtual-dex/validators/account/app_unlock.ak
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use aiken/transaction.{ScriptContext, Transaction, WithdrawFrom}
use aiken/transaction/value.{PolicyId, merge, zero}
use aiken_virtual_dex/common.{get_all_value_to,
only_input_datum_with, value_geq}
use aiken_virtual_dex/types.{OracleDatum}
use aiken_virtual_dex/types.{AccountOracleDatum}
use sidan_utils/address.{address_script_hash}
use sidan_utils/extra_signatories.{key_signed}

Expand All @@ -15,7 +15,7 @@ pub fn account_app_unlock_logic(
let ScriptContext { purpose, transaction } = context
let Transaction { inputs, outputs, extra_signatories, .. } = transaction
expect WithdrawFrom(_) = purpose
expect OracleDatum { operation_key, .. }: OracleDatum =
expect AccountOracleDatum { operation_key, .. }: AccountOracleDatum =
only_input_datum_with(transaction.reference_inputs, oracle_nft, "")

let (is_only_single_script_address, maybe_script_address, account_input_value) =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use aiken/transaction.{InlineDatum, Input, ScriptContext, WithdrawFrom}
use aiken_virtual_dex/types.{
AccountDatum, AccountEmergencyActionPhase1Redeemer, EmergencyUnlockPhase1,
AccountDatum, AccountEmergencyPhase1Redeemer, EmergencyUnlockPhase1,
EmergencyUnlockPhase2,
}
use aiken_virtual_dex/utils.{get_emergency_token_name}
Expand All @@ -11,13 +11,13 @@ use sidan_utils/validity_range.{valid_before}

pub fn account_emergency_unlock_phase_1_logic(
emergency_token: ByteArray,
redeemer: AccountEmergencyActionPhase1Redeemer,
redeemer: AccountEmergencyPhase1Redeemer,
context: ScriptContext,
) -> Bool {
let ScriptContext { purpose, transaction } = context
expect WithdrawFrom(_) = purpose

let AccountEmergencyActionPhase1Redeemer { owner, own_input, initiate_before } =
let AccountEmergencyPhase1Redeemer { owner, own_input, initiate_before } =
redeemer
let current_address = own_input.output.address
expect [own_output] =
Expand Down
4 changes: 2 additions & 2 deletions lib/aiken-virtual-dex/validators/account/user_unlock.ak
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use aiken/transaction.{ScriptContext, WithdrawFrom}
use aiken/transaction/value.{PolicyId}
use aiken_virtual_dex/common.{only_input_datum_with}
use aiken_virtual_dex/types.{OracleDatum}
use aiken_virtual_dex/types.{AccountOracleDatum}
use sidan_utils/extra_signatories.{all_key_signed}

pub fn account_user_unlock_logic(
Expand All @@ -12,7 +12,7 @@ pub fn account_user_unlock_logic(
) -> Bool {
let ScriptContext { purpose, transaction } = context
expect WithdrawFrom(_) = purpose
expect OracleDatum { operation_key, .. }: OracleDatum =
expect AccountOracleDatum { operation_key, .. }: AccountOracleDatum =
only_input_datum_with(transaction.reference_inputs, oracle_nft, "")
all_key_signed(transaction.extra_signatories, [owner, operation_key])
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,31 @@
use aiken/transaction.{InlineDatum, Output, ScriptContext, Spend, Transaction}
use aiken_virtual_dex/types.{OracleDatum, OracleRedeemer, RotateKey, StopApp}
use aiken_virtual_dex/types.{
AccountOracleDatum, AccountOracleRedeemer, RotateKey, StopApp,
}
use sidan_utils/extra_signatories.{all_key_signed, key_signed}
use sidan_utils/mints.{only_minted_token}
use sidan_utils/outputs.{outputs_at_with}

pub fn oracle_validator_logic(
datum: OracleDatum,
redeemer: OracleRedeemer,
pub fn account_oracle_logic(
datum: AccountOracleDatum,
redeemer: AccountOracleRedeemer,
context: ScriptContext,
) {
let ScriptContext { purpose, transaction } = context
when purpose is {
Spend(_) -> {
let Transaction { outputs, mint, extra_signatories, .. } = transaction
let OracleDatum { oracle_nft, oracle_address, stop_key, .. } = datum
let AccountOracleDatum { oracle_nft, oracle_address, stop_key, .. } =
datum

when redeemer is {
RotateKey { new_operation_key, new_stop_key } -> {
expect [own_output] =
outputs_at_with(outputs, oracle_address, oracle_nft, "")
expect InlineDatum(dat) = own_output.datum
expect own_datum: OracleDatum = dat
expect own_datum: AccountOracleDatum = dat
let datum_correct =
own_datum == OracleDatum {
own_datum == AccountOracleDatum {
..datum,
operation_key: new_operation_key,
stop_key: new_stop_key,
Expand Down
Loading

0 comments on commit 53192cc

Please sign in to comment.