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.