Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Audit Meta #1

Open
zmrocze opened this issue Jun 24, 2024 · 4 comments
Open

Audit Meta #1

zmrocze opened this issue Jun 24, 2024 · 4 comments

Comments

@zmrocze
Copy link
Contributor

zmrocze commented Jun 24, 2024

@Renegatto
Copy link

Renegatto commented Jun 26, 2024

My notes, including user and protocol requirements:

Design notes:

Some high-level notes and assumptions about the protocol design based on the spec overview.
These are not clearly specified and may not match the actual implementation.

s - concrete protocol instance.

Quantity relations between entities:

1 Token MP s
↔ 1 UpdateableAddresses Validator s
↔ 1 NFT s
↔ 1 NFT MP s
↔ 0+ Token s

Scripts relations:

Token MP s
-knows→ UpdateableAddresses Validator s -knows→ NFT MP s

Parametrized scripts:

  • Token MP s params:
    • UpdateableAddresses Validator s
    • NFT MP s
  • UpdateableAddresses Validator s params:
    • NFT MP s
  • NFT MP s params:
    • ? (maybe TxInput)

User requirements

U0: I want to always be able to mint and burn existing tokens

Follows:

  • Protocol should not stall or halt
    • ⇒ All protocol UTxOs should remain spendable
    • ⇒ Protocol should always have a set of allowed Txs constructable by the user

U1: Have no restrictions that have no impact on safety

U2: I want that if amount of compromised signer keys is less or equal to a half, signers are remain in their power

That actually follows from U3, so even if adversary have half of the keys, it can't change protocol state using only them, while signers can use compromised keys as well, having majority this way.

U3: I want any one to be able to interact with the protocol iff having majority of signers

U4: I don't want to have any unspendable funds on the protocol scripts

  • Any UTxO on the protocol MUST be spendable iff it is not unspendable on their own (e.g. attempt to spend the output would exceed mem/cpu limits).

U5: I want any user to be able to freely burn their tokens of this protocol

Preconditions

State thread is valid and ready

  • NFT MUST be always unique single token under it's CS.
  • NFT MUST be minted and output along with the correct datum as a valid state thread UTxO to a UpdateableAddresses validator parametrized by it (so it belongs to the corresponding protocol instance)

Protocol requirements

All the protocol requirements MUST imply preconditions.

P0: Every NFT token can ONLY be found at the only UpdateableAddresses validator at ANY moment of time

Follows from: U0

P1: The amount of signers MUST be odd

Follows from: U1, U2, U3

P2: Protocol UTxOs MUST contain only necessary assets and datum

Because of common vilnerabilities:

  • unbounded-protocol-datum
  • unbounded-protocol-value
  • foreign-utxo-tokens

Follows from U0

P3: UpdateableAddresses MUST only allow spending of it's NFT in a Tx with a strict majority of signatures

Because of common vilnerabilities:

  • missing-utxo-authentication

Follows from U3

P4: UTxO containing NFT token MUST have valid state thread datum

Because of common vilnerabilities:

  • arbitrary-utxo-datum

Follows from U3, U0

Corresponding UpdateableAddresses validator MUST ensure that.

P5: Token MP MUST only allow minting in a Tx with the corresponding NFT being spent

Because of common vilnerabilities:

  • missing-utxo-authentication

Follows from U3, U0

P6: UpdateableAddresses MUST allow spending of any UTxO that does not contain NFT

Because of common vilnerabilities:

  • locked-value

Follows from U1, U4

P7: Protocol behaviour MUST not change regardless of any protocol token name change

Because of common vilnerabilities:

  • other-token-names

P8: Protocol MUST have correct arithmetic

Because of common vilnerabilities:

  • division-by-zero
  • rounding-error

Follows from U0

P9: Protocol MUST not halt or stale

Follows from U0

P10: multiple-satisfaction is not possible

Because of common vilnerabilities:

  • multiple-satisfaction

It should not be possible, because:

  • there is nothing to pay from the user
  • different protocol instances do not have any other ways to interact
  • there is only one UTxO at UpdateableAddresses
  • there is only one MP to mint or burn

P11: Burning tokens MUST not be constrained

P12: Burning tokens MUST not interfere with protocol state thread update

So it should not be possible to burn tokens and put a lot of trash tokens into a state thread UTxO in the same Tx.

Covered by P2, but just in case.

Because of common vilnerabilities:

  • unbounded-protocol-value

TODO: consider staking credentials

@zmrocze
Copy link
Contributor Author

zmrocze commented Jun 26, 2024

look for problems with:

  • 0 owners
  • min threshold greater than num of owners
  • protocol can be used parametrized many times

requirements

token scripts

  1. Can only mint a token if owners accept with a defined threshold.
  2. Can only mint if spending output with NFT.

NFT

  1. After creation, there is always single NFT token in existance.
  2. The token is held at UpgradeableAddresses script address.

UpgradeableOwners

User

  1. Protocol allows addition or removal of owners provided the minimum number of owners agree.
  2. Protocol allows the changing of the minimum required number of signatures for acceptance, provided the minimum number of owners agree.
  3. Any Token owner can freely burn the tokens.
  4. Protocol allows minting of new Tokens provided the minimum number of owners agree.
  5. As a user I cannot steal Tokens (meaning they land where agreed by threshold).

Protocol

  1. The NFT containing output stores the minimum threshold and owners' addresses.
  2. The minimum threshold is no greater than the number of owners and greater than 1.
  3. TODO: The number of owners is ___.
  4. Token minting transaction doesn't change owners and threshold.

@rmgaray
Copy link

rmgaray commented Jun 26, 2024

Goal:

To mint tokens safely and allow holders of these tokens to burn them freely.

Requirements:

  1. To mint the asset, there must be at least min_threshold signatures from the minters_set.
  2. Any owner of the asset must be able to burn it if desired.
  3. The minters_set must be updatable. Any addition/removal of owners to/from this set must have min_threshold signatures from the minters_set.
  4. The minters_set must have at least 2 members.
  5. The min_threshold must be updatable. Any change to this number must have min_threshold signatures from the minters_set.
  6. The min_threshold must always be within the range of [2; |minters_set|]

Questions:

What if the same public key hash is used more than once in the datum? Depending on the implementation, this could be a problem.

@groscoe
Copy link

groscoe commented Jun 26, 2024

User actions

  • Minting the state thread token

    • Who can initiate?

      • Anybody (but only once per protocol instance).
    • Why?

      • To create an authentication witness for the state thread
        utxo.
    • Under which conditions?

      • The state thread token policy must be parameterized by a
        TxOutRef.

        • NOTE: the policy could be
          parameterized by the UpgradableAddresses script's
          address, but this would cause a cyclic dependency, since
          the script needs to check the policy symbol of the state
          thread token.
      • The UTxO referred by the TxOutRef must be an input to the
        transaction.

      • Exactly one token must be minted.

      • The output containing the token must have a valid datum.

        • The datum must contain at least 2 pubkey hashes
          (smallest value for the min threshold)

        • The datum must have the pubkey hashes of all the desired
          signatories.

          • (Optional) These should be checked to be distinct.

          • (Optional) There should be an upper limit to the
            number of signatories. Otherwise, the datum could
            grow unbounded and result in an unspendable utxo.

        • The minimum threshold in the datum must be at least 2.

        • The minimum threshold should be at most the total number
          of pubkey hashes.

      • The output containing the token must be sent to a script
        address.

      • (Optional): The output containing the token should not be
        able to have an unbounded number of native assets (ideally
        only the state thread token). This avoids having a UTxO
        that's too large to be spendable.

      • (Optional): The state thread token must not be able to be
        burned. This check can be forwarded to the validator instead
        by requiring transactions to always have an output
        containing the token sent back to the script's address.

    • Consequences?

      • The UTxO referenced will be spent and therefore no new
        tokens with this policy will be able to be minted.

      • The protocol's state thread UTxO (token + datum) will sit at
        the desired address.

    • NOTE: Reading the specification, it looks like they're minting
      the token and sending it to the script in two different
      transactions (and thus no checks about the output address or
      datums would be included). This needs to be checked in the code,
      as this is mildly dangerous (can result in an unspendable output
      due to a malformed datum and the need to mint a new token -
      though, as this would happen before the protocol is launched,
      it's probably not big deal).

  • Minting the protocol tokens

    • Who can initiate?

      • Enough datum signatories to meet the threshold.
    • Under which conditions?

      • The name of the token being minted should be "correct".

        • NOTE: This could be checked either in the protocol
          token's minting policy or in the validator. If in the
          former, different tokens may be validly minted in a
          single transaction.
      • The transaction must be signed by at least the minimum
        threshold of signatories from the state thread datum.

      • The state thread output must be an input to the transaction.

      • An output containing the state thread token and an
        unchanged state thread datum must be sent back to the
        validator's address (i.e. the same address as the input
        state thread utxo's).

        • (Optional) it should not be possible to add an unbounded
          number of native assets (ideally none other than the
          state thread token) to the state thread utxo. This
          prevents unspendable utxos due to size.
          • NOTE: In particular, since there's no bound to the
            number of tokens being minted, sending
            them to the script's
            output could result in an unspendable utxo. This
            might not be a problem since the transaction still
            needs to be signed by the required PKhs, and could
            even be used as a way to destroy the protocol and
            prevent new tokens being minted, if so desired
            (though there are much better ways).
    • Consequences?

      • Whatever number of the desired tokens will be minted and
        sent to the payer's address (if this is not checked, see the
        note about the state thread utxo above).

      • The state thread will be consumed (and replaced). This means
        that no other actions other than burning the tokens can take
        place simultaneously.

  • Burning the distribution tokens

    • Who can initiate?

      • Any holder.
    • Under which conditions?

      • At any time. No checks are needed. The ledger will ensure
        that the burned tokens must an input to the transaction.
    • Consequences?

      • The desired number of tokens will be burned. Multiple of
        these transactions can be placed in the same block.
  • Adding or removing a signatory to the state thread datum

    • Who can initiate?

      • Enough datum signatories to meet the threshold.
    • Under which conditions?

      • The transaction must be signed by at least the minimum
        threshold of signatories from the state thread datum.

      • The state thread output must be an input to the transaction.

      • An output containing the state thread token and an
        unchanged state thread datum must be sent back to the
        validator's address (i.e. the same address as the input
        state thread utxo's).

        • NOTE: see the note above about additional assets in the
          state thread utxo.
      • The number of signatories in the output datum must be at
        least as large as the minimum threshold.

      • The desired set of pubkey hashes must be listed in the
        output datum.

        • (Optional) The number of signatories in the new datum
          should be limited, so that it doesn't grow without
          bounds.
    • Consequences?

  • Removing a signatory from the state thread datum

    • Who can initiate?

      • Enough datum signatories to meet the threshold.
    • Under which conditions?

      • The transaction must be signed by at least the minimum
        threshold of signatories from the state thread datum.

      • The state thread output must be an input to the transaction.

      • An output containing the state thread token and an
        unchanged state thread datum must be sent back to the
        validator's address (i.e. the same address as the input
        state thread utxo's).

        • NOTE: see the note above about additional assets in the
          state thread utxo.
    • Consequences?

      • The state thread will be consumed (and replaced). This means
        that no other actions other than burning the tokens can take
        place simultaneously.
  • Changing the minimum number of signatories

    • Who can initiate?

      • Enough datum signatories to meet the threshold.
    • Under which conditions?

      • The transaction must be signed by at least the minimum
        threshold of signatories from the state thread datum.

      • The state thread output must be an input to the transaction.

      • An output containing the state thread token and a valid
        thread datum must be sent back to the validator's address
        (i.e. the same address as the input state thread utxo's).

        • NOTE: see the note above about additional assets in the
          state thread utxo.
      • The output datum must have the desired threshold.

      • The new threshold must be at most the number of pubkey
        hashes present in the datum.

      • The new threshold must be at least 2.

    • Consequences?

      • The state thread will be consumed (and replaced). This means
        that no other actions other than burning the tokens can take
        place simultaneously.

      • NOTE: in principle, there's nothing stopping this
        transaction to happen simultaneously with the other datum
        updates. In that case, all the properties of both
        transactions must be true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants