-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #67 from cardano2vn/develop
Develop
- Loading branch information
Showing
66 changed files
with
2,867 additions
and
488 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.