Assessment reports>Mina Token Bridge>Informational findings>Fixed number of validators
Category: Coding Mistakes

Fixed number of validators

Informational Severity
Informational Impact
N/A Likelihood

Description

The bridge is expected to have some validators, but the Mina contract has a fixed number of validators on the functions.

@method async unlock(
  amount: UInt64,
  receiver: PublicKey,
  id: UInt64,
  tokenAddr: PublicKey,
  useSig1: Bool,
  validator1: PublicKey,
  sig1: Signature,
  useSig2: Bool,
  validator2: PublicKey,
  sig2: Signature,
  useSig3: Bool,
  validator3: PublicKey,
  sig3: Signature,
) {
  const managerZkapp = new Manager(this.manager.getAndRequireEquals());
  managerZkapp.isMinter(this.sender.getAndRequireSignature());
  const msg = [
    ...receiver.toFields(),
    ...amount.toFields(),
    ...tokenAddr.toFields(),
  ]
  this.validateValidator(
    useSig1,
    validator1,
    useSig2,
    validator2,
    useSig3,
    validator3,
  );

  this.validateSig(msg, sig1, validator1, useSig1);
  this.validateSig(msg, sig2, validator2, useSig2);
  this.validateSig(msg, sig3, validator3, useSig3);
  const token = new FungibleToken(tokenAddr)
  await token.mint(receiver, amount)
  this.emitEvent("Unlock", new UnlockEvent(receiver, tokenAddr, amount, id));
}
public async validateValidator(
  useSig1: Bool,
  validator1: PublicKey,
  useSig2: Bool,
  validator2: PublicKey,
  useSig3: Bool,
  validator3: PublicKey,
) {

  let count = UInt64.from(0);
  const zero = Field.from(0);
  const falseB = Bool(false);
  const trueB = Bool(true);
  const validatorManager = new ValidatorManager(this.validatorManager.getAndRequireEquals());
  const validateIndex = async (validator: PublicKey, useSig: Bool) => {
    const index = await validatorManager.getValidatorIndex(validator);
    const isGreaterThanZero = index.greaterThan(zero);
    let isOk = Provable.if(useSig, Provable.if(isGreaterThanZero, trueB, falseB), trueB);
    isOk.assertTrue("Public key not found in validators");
  };

  const notDupValidator12 = Provable.if(useSig1.and(useSig2), Provable.if(validator1.equals(validator2), falseB, trueB), trueB);
  const notDupValidator13 = Provable.if(useSig1.and(useSig3), Provable.if(validator1.equals(validator3), falseB, trueB),trueB);
  const notDupValidator23 = Provable.if(useSig2.and(useSig3), Provable.if(validator2.equals(validator3), falseB, trueB), trueB);

  const isDuplicate = Provable.if(
    notDupValidator12.and(notDupValidator13).and(notDupValidator23),
    falseB,
    trueB,
  );

  isDuplicate.assertFalse("Duplicate validator keys");

  count = Provable.if(useSig1, count.add(1), count);
  count = Provable.if(useSig2, count.add(1), count);
  count = Provable.if(useSig3, count.add(1), count);
  count.assertGreaterThanOrEqual(this.threshold.getAndRequireEquals(), "Not reached threshold");

}

Impact

The fixed number of validators could cause failure in reaching the expected threshold.

Recommendations

We recommend adding a dynamic array for the validators.

Remediation

Sotatek acknowledged the finding and provided the following comment:

Because Mina contracts have storage limitations, we can only store 8 slots in global storage. Therefore, we are hardcoding the validators.

Zellic © 2025Back to top ↑