Skip to main content

Insufficient Staking Control

From MLabs Common Plutus Vulnerabilities

11.Insufficient staking key control

Identifie:r insufficient-staking-control

Property statement: All scripts explicitly account for staking credentials.

Test: A transaction successfully changes or incorrectly sets the staking credential of a UTxO locked by a validator of the protocol. Alternatively, a transaction sets an arbitrary staking credential for an output being locked by an external credential and holding value consumed from the protocol.

Impact:

  • Unpredictable addresses
  • Illegitimate staking rewards

Further explanation: When writing the logic for a Plutus script, it is easy to focus too much on the set of rules that must be enforced by a validator and start thinking of these rules as solely defining the Cardano addresses. This is, treating validator hashes and addresses interchangeably. An example of such behaviour is illustrated by the following excerpt:

vulnValidator __ ctx =
traceIfFalse “Must continue tokens” (txOutValue ownInput == contVal)
where
ownInput = txInInfoResolved $ findOwnInput ctx
ownValidatorHash = ownHash ctx
[(_, contVal)] = scriptOutputsAt ownValidatorHash (scriptContextTxInfo ctx)

The validator above tries to make sure that after consuming a UTxO locked by vulnValidator, an output holding the same value is locked back. However, it forgets about the staking credentials, so the output can actually be locked in a very large number of addresses.

This is because addresses are composed of credentials that control the spending of UTxOs and staking credentials that control the claiming of ADA staking rewards. Therefore, validation would succeed as long as the output is locked in an address which has ownHash as credential. However, there are as many such addresses as possible public keys or script hashes for a staking credential.

By exploiting this, anybody could send the funds to an address with a staking credential controlled by them. This would not grant them control over the funds, since they are still guarded by the validator's logic, but would grant them control over the staking rewards generated by all the ADA present in the locked output.

Apart from losing control over staking rewards, ignoring the staking credentials could have further consequences and result in a catastrophic outcome. This is because since the UTxO holding the funds can live in a big spectrum of addresses, it becomes more difficult to reason about the rules that control their spending.

For instance, to prevent a multiple satisfaction attack, a validator could have a rule ensuring that only one input coming from the address of the input being validated is present in the transaction. This works correctly assuming that all relevant funds are locked in the same address as the input being validated. However, as soon as part of the funds end up in an address with the same credential but different staking credential, the check could be by-passed and tokens could leak.

Finally, this not only applies when locking UTxOs in scripts but also when sending funds from a script to a public key. If the script controlling it only checks that funds are correctly sent to the public key but neglects the staking credentials, the value could be sent to a mangled address, where the public key is correct but an arbitrary staking key has been used. Although the legit owner of the funds would still have access to them, the right to claim staking rewards generated by the ADA in these funds would temporarily belong to an actor different than the legit owner of the funds.

This problem is prevented by explicitly checking the staking credentials, taking into account complete addresses instead of only the credentials controlling the spending of funds.