Design and architecture for Charli3 ODV multisig oracle are described in this doc. Flowcharts that were used in confluence document are uploaded to docs-media folder. See also presentation slides where that idea was first described.
Write validators in the validators folder, and supporting functions in the lib folder using .ak as a file extension.
validator my_first_validator {
spend(_datum: Option<Data>, _redeemer: Data, _output_reference: Data, _context: Data) {
True
}
}For mainnet:
aiken buildFor testnets:
aiken build --env testnet --trace-filter user-definedaiken.toml
[config.default]
network_id = 41Or, alternatively, write conditional environment modules under env.
You can write tests in any module using the test keyword. For example:
use config
test foo() {
config.network_id + 1 == 42
}To run all tests, simply do:
aiken checkTo run only tests matching the string foo, do:
aiken check -m fooIf you're writing a library, you might want to generate an HTML documentation for it.
Use:
aiken docsThis command is run on every commit if you install the git hook by running:
root="$(pwd)" && ln -s "$root/hooks/pre-commit" "$root/.git/hooks/pre-commit"Find more on the Aiken's user manual.
Simply install latest version of aiken (change version tag) nix profile install github:aiken-lang/aiken/v1.1.16#aiken.
Validators trace messages and codes with their mapping are described here.
To reduce script size we can remove traces altogether, but then it's hard to know where error is coming from, especially when doing debugging in testnets. Other option is to use short trace and error codes instead of messages, this document describes them.
Direct failures that stop evaluation.
- E1 –
oracle_nftswas invoked outside of a minting context. - E2 –
oracle_managervalidators expectspendpurpose and reject anything else. - E3 –
oracle_managerreceived an unsupported redeemer/state transition. - E4 –
consensus.medianwas asked to operate on an empty list. - E5 – list elements expected in ascending order (used for feed/value ordering checks).
- E6 – feed verification keys must be strictly ascending when iterating.
- E7 – node list must be non-empty when validating feed order.
Trace message is added to the list (evaluation context) when evaluation comes to a particular code branch, it will be added on every evaluation failure as well as success.
- T1 –
ScaleTokenmint path (adding fresh Reward/AggState UTxOs). - T2 –
ScaleTokenburn path (requiring the matching inputs to be consumed). - T3 –
find_own_protocol_policy_idextracts the oracle policy id from inputs. - T4 –
get_current_timederives the midpoint from the validity range. - T5 –
auth_by_nftvalidates the platform NFT witness. - T6 –
check_nodes_multisigverifies node signatures against settings. - T7 –
spends_protocol_nft_inputschecks the number of spent oracle NFTs. - T8 –
spends_one_script_utxo_with_nftenforces single NFT script input usage. - T9 –
spends_one_account_utxo_for_aggregationvalidates aggregation account input. - T10 –
returns_empty_account_outputsconfirms new reward accounts are zeroed. - T11 –
returns_empty_aggstate_outputsconfirms new AggState outputs are empty. - T12 –
find_out_datum_and_valuefetches output datum/value by NFT. - T13 –
find_out_datum_and_value_with_allowing_assetvariant allowing extra asset. - T14 –
find_referenced_datumloads datum from reference inputs. - T15 –
find_in_datumretrieves inline datum from an input. - T16 –
count_dismissed_reward_accountscounts reward inputs dismissed. - T17 –
check_reward_accounts_in_to_out_mappingmatches reward inputs to outputs. - T18 –
get_length_and_check_strict_orderensures integer list ascending order. - T19 –
does_not_produce_own_nft_outputsforbids minting extra protocol NFTs. - T20 –
is_aggstate_expiredchecks aggregation window expiry. - T21 –
convert_reward_pricesconverts fees using reference prices. - T22 –
conserves_utxo_valueenforces exact input/output value conservation. - T23 –
check_utxo_size_safety_bufferkeeps reward accounts above min ADA. - T24 –
check_reward_distributionvalidates reward distribution maps. - T25 –
validate_message_and_count_nodeschecks median message ordering. - T26 –
check_settings_sanitykeeps invariant settings untouched. - T27 –
validate_settings_formasserts settings format and token references. - T28 –
check_pause_does_not_change_settingsensures pause toggles only the flag. - T29 –
find_node_by_signatureresolves the signing node. - T30 –
check_node_received_rewardvalidates node withdrawals. - T31 –
check_platform_received_rewardvalidates platform fee withdrawals. - T32 –
check_nodes_updatevalidates node list additions/removals. - T33 –
validate_dismissing_periodchecks reward dismissal timeout. - T34 – interquartile range collapsed to zero (IQRFence degeneration).
This repository is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
License Rationale
Charli3 uses a combination of OSI-approved open-source licenses, primarily AGPL-3.0 and MIT, depending on the role of each repository within the ecosystem. Repositories that implement core or protocol-critical logic are licensed under AGPL-3.0 to ensure that improvements and modifications remain transparent and benefit the entire ecosystem, including node operators, developers, and token holders, while maintaining full OSI compliance. This may include both on-chain and select off-chain components where protocol logic and token usage are integral.
Repositories focused on tooling, SDKs, and supporting components are typically licensed under the MIT License to promote broad adoption, flexibility, and ease of integration.
AGPL-3.0 is applied where reciprocal openness is important to protect shared protocol infrastructure, while MIT is used where permissiveness and developer flexibility are the primary goals.
Please refer to each repository’s LICENSE file for the specific terms that apply.
See LICENSE for the full license text.
Full commercial licenses available upon request by contacting sales@charli3.io.
Charli3 maintains and supports only official deployments that use the $C3 token and unmodified protocol economics.