Skip to content

Commit

Permalink
Merge pull request #67 from cardano2vn/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
independenceee authored Nov 4, 2024
2 parents e81700d + 3db5e64 commit 1245db3
Show file tree
Hide file tree
Showing 66 changed files with 2,867 additions and 488 deletions.
128 changes: 127 additions & 1 deletion contract/README.md
Original file line number Diff line number Diff line change
@@ -1 +1,127 @@
# CIP68Generator - Contract
use aiken/collection/list
use aiken/crypto.{ScriptHash, VerificationKeyHash}
use cardano/address
use cardano/assets.{AssetName, PolicyId, without_lovelace}
use cardano/minting
use cardano/transaction.{Transaction}
use cardano/tx.{verify_signature}
use cardano/value
use cip68generator/types.{Burn, Mint, MintRedeemer}
use cip68generator/utils
use types/cip68
use validation/find

// validator - mint
// parameters (exchange_address, store_validator)
validator mint(store: ScriptHash) {
mint(redeemer: MintRedeemer, policy_id: PolicyId, transaction: Transaction) {
let Transaction { inputs, outputs, extra_signatories, mint, .. } =
transaction

let mint_flatten =
mint
|> without_lovelace()
|> assets.flatten()

when redeemer is {
Mint -> {
let first_tx_id = find.first_input_txid(inputs)
let first_tx_index = find.first_input_index(inputs)

let reference_token = utils.token_prefix(mint_flatten, cip68.prefix_100)
let user_token = utils.token_prefix(mint_flatten, cip68.prefix_222)

let check_none_token =
utils.check_none_token(user_token, reference_token)

when check_none_token is {
False -> False
True -> {
let reference_value =
assets.from_asset(policy_id, reference_token, 1)
let store_address = address.from_script(store)
let output_utxo =
find.output_by_addr_value(outputs, store_address, reference_value)

and {
first_tx_index < 256,
list.length(mint_flatten) >= 2,
minting.exact(mint_flatten, policy_id, reference_token, 1)?,
utils.check_output_utxo(output_utxo, extra_signatories)?,
}
}
}
}

Burn -> True
}

}

else(\_) {
fail
}
}

use aiken/collection/list
use aiken/crypto.{ScriptHash, VerificationKeyHash}
use cardano/address
use cardano/assets.{AssetName, PolicyId, without_lovelace}
use cardano/minting
use cardano/transaction.{Transaction}
use cardano/tx.{verify_signature}
use cardano/value
use cip68generator/types.{Burn, Mint, MintRedeemer}
use cip68generator/utils
use types/cip68
use validation/find

// validator - mint
// parameters (exchange_address, store_validator)
validator mint(store: ScriptHash) {
mint(redeemer: MintRedeemer, policy_id: PolicyId, transaction: Transaction) {
let Transaction { inputs, outputs, extra_signatories, mint, .. } =
transaction

let mint_flatten =
mint
|> without_lovelace()
|> assets.flatten()

when redeemer is {
Mint -> {
let first_tx_id = find.first_input_txid(inputs)
let first_tx_index = find.first_input_index(inputs)

let reference_token = utils.token_prefix(mint_flatten, cip68.prefix_100)
let user_token = utils.token_prefix(mint_flatten, cip68.prefix_222)

let check_none_token = utils.check_none_token(user_token, reference_token)

when reference_token is {
Some(reference_token) -> {
let reference_value =
assets.from_asset(policy_id, reference_token, 1)
let store_address = address.from_script(store)
let output_utxo =
find.output_by_addr_value(outputs, store_address, reference_value)

and {
first_tx_index < 256,
list.length(mint_flatten) >= 2,
minting.exact(mint_flatten, policy_id, reference_token, 1)?,
utils.check_output_utxo(output_utxo, extra_signatories)?,
}
}
_ -> fail @"No matching asset found for the given prefix"
}
}
Burn -> True
}

}

else(\_) {
fail
}
}
20 changes: 2 additions & 18 deletions contract/lib/cip68generator/types.ak
Original file line number Diff line number Diff line change
@@ -1,30 +1,14 @@
use aiken/crypto.{VerificationKeyHash}
use cardano/assets.{AssetName, PolicyId}

pub type Asset {
policy_id: PolicyId,
asset_name: AssetName,
}

pub type Extra {
address: VerificationKeyHash,
has_change: Bool,
asset: Asset,
}

pub type StoreDatum {
metadata: Pair<Data, Data>,
version: Int,
extra: Extra,
}

// the redeemer using mint validator
pub type MintRedeemer {
Mint
Burn
}

// the redeemer using store validator
pub type StoreRedeemer {
Update
Remove
Redeem
}
100 changes: 95 additions & 5 deletions contract/lib/cip68generator/utils.ak
Original file line number Diff line number Diff line change
@@ -1,15 +1,105 @@
use aiken/collection/list
use cardano/assets.{flatten, without_lovelace}
use aiken/crypto.{ScriptHash, VerificationKeyHash}
use aiken/primitive/bytearray
use cardano/address.{Address}
use cardano/assets.{AssetName, PolicyId, flatten, lovelace_of, without_lovelace}
use cardano/transaction.{InlineDatum, Output}
use cip68generator/types.{StoreDatum}
use cardano/tx
use types/cip68.{CIP68}

pub fn check_output_utxo(output: Output) -> Bool {
// check the output utxos containing the reference nft
pub fn check_output_utxo(output: Output, vks: List<VerificationKeyHash>) -> Bool {
expect InlineDatum(data) = output.datum
expect _metadatum: StoreDatum = data
expect metadatum: CIP68 = data
expect name: ByteArray = cip68.get(metadatum, "name")
expect image: ByteArray = cip68.get(metadatum, "image")
expect media_type: ByteArray = cip68.get(metadatum, "mediaType")
expect author: VerificationKeyHash = cip68.get(metadatum, "author")

let output_value =
output.value
|> without_lovelace()
|> flatten()

list.length(output_value) == 1
and {
bytearray.length(name) > 0,
bytearray.length(image) > 0,
bytearray.length(media_type) > 0,
tx.verify_signature(vks, author),
list.length(output_value) == 1,
}
}

// get asset name from mint flatten
pub fn token_prefix(
flat: List<(PolicyId, AssetName, Int)>,
prefix: ByteArray,
) -> Option<AssetName> {
let exist =
list.find(
flat,
fn((policy_id, asset_name, amount)) {
bytearray.starts_with(asset_name, prefix)
},
)
when exist is {
Some((policy_id, asset_name, amount)) -> Some(asset_name)
None -> None
}
}

pub fn check_none_token(
user_token: Option<AssetName>,
reference_token: Option<AssetName>,
) -> Bool {
if user_token == None || reference_token == None {
False
} else {
True
}
}

pub fn check_address(output: Output, address: Address) -> Bool {
output.address.payment_credential == address.payment_credential
}

// The function checks whether the output exists or not
pub fn check_none_output(
output_store: Option<Output>,
output_exchange: Option<Output>,
) -> Bool {
// If one of the 3 outputs does not exist, the function will return False
if output_store == None || output_exchange == None {
False
} else {
// Otherwise, the function will return True
True
}
}

pub fn find_output(
outputs: List<Output>,
price: Int,
address: Address,
) -> Option<Output> {
list.find(
outputs,
fn(output) { check_amount(output, price) && check_address(output, address) },
)
}

pub fn check_price_duplicate(out_sell: Output, out_royal: Output) -> Bool {
lovelace_of(out_sell.value) > lovelace_of(out_royal.value)
}

pub fn check_address_duplicate(
output_author: Output,
output_exchange: Output,
) -> Bool {
output_author.address.payment_credential == output_exchange.address.payment_credential
}

// The function checks the amount
pub fn check_amount(output: Output, price: Int) -> Bool {
lovelace_of(output.value) >= price
}
Loading

0 comments on commit 1245db3

Please sign in to comment.