Info

Download ZIP (175.4 KB)

Testing and Issues

You can test this entry and submit issues during the testing period of the TON Trustless Bridge Challenge contest.

Entries with serious issues will not be able to win the contest, but even minor issues might be important for overall results.

Voting

55
by rating

Issues

```
val requiredWeight = valTotalWeight * 2 / 3;
assert(accWeight >= requiredWeight) throw ERR_NOT_ENOUGH_WEIGHT;
```

While checking signature:
- division is used - it's a bad idea for a smart contract;
- `accWeight` must be strictly bigger than `requiredWeight`;
- the hash of data is recalculated each iteration, but it is possible to do it once.
1
Shiny Giraffe Feb 6 at 10:59
Hello and thank you for your feedback.
Note that detailed explanation is moved to picture because of text size limit, be sure to check it out.

>> - division is used - it's a bad idea for a smart contract;
There are no issues from rounding down (it even helps), and no overflow risk. See more details in the attached picture.

>> - `accWeight` must be strictly bigger than `requiredWeight`;
This is a bit controversial topic, there are differently edged weight comparisons in different parts of Node code. In practice should never cause any problems due to way how weights are calculated. See more details in the attached picture.

- the hash of data is recalculated each iteration, but it is possible to do it once.
There is no hash recalculation in any loop, but I did some extended clarifications in the attached picture.
Solid implementation of lite-client and tx-checker, but "hints"-based tx-search in proof (insecure). Quite a lot additional functionality for UX improvement. For instance shard-optimization and attempt to implement shard-transaction checks (unfortunately too simplified to work in production).

More info on issues: https://contest.com/docs/TrustlessBridgeChallengeAssessment
1
Shiny Giraffe Feb 19 at 14:24
Hello and thank you for your assessment!

I have identified some of the bugs after the submission and fixed them in "post-contest fixes" branch (https://github.com/Skydev0h/SkyBridge/tree/pcf) that include some very basic fixes to make it more secure and production-ready. The *most* secure approach would be to traverse HashMapAug properly, but, for efficient implementation, several new instructions (easily implemented) should be added to TVM.

Overall, surely, for production usage the contract would need some refinement and a proper audit, and that relates not only to the SC itself, but to the accompanying Typescript code, that, in some places is more like a hastily written PoC than actual production library (although I attempted some unlinking to be able to use it in Jest tests).
Division with round down is a problem and it's not helping at all. You just lowering required weight by doing that, and allowing invalid block to be accepted by smart contract.

Here is snippet you can insert in browser console and see that comparison with division returns TRUE where valid calculation should return FALSE.

var signedWeight = 3;
var totalWeight = 5;
var isEnough_usingDiv = signedWeight >= Math.floor((totalWeight * 2 / 3));
var isEnough_usingMul = signedWeight * 3 >= totalWeight * 2;

console.log(isEnough_usingDiv, isEnough_usingMul);
Shiny Giraffe Feb 6 at 13:38
πŸ‘‹ Thank you for your clarification and an example.

πŸ˜” Unfortunately, like always, text is too big, so complete response and explanation is provided in the attached picture.

✍️ Long story short - in real TON networks using weights provided by the Elector, and given limits of maximum amount of validators, precision of weight and maximum weight imbalance factor the problem is practically impossible to replicate. Although for peace of mind strict comparison can be used, that's a valid point.

🧐 More detailed explanation can be examined in the attached picture.
In `processCheckBlock` function you check that the block is not from past epoch, but you don't check that the block is not from future epoch.
Shiny Giraffe Feb 9 at 23:38
πŸ‘‹ Hello there, thank you for your comment.

☝️ However, actually, there is no exact definition of "epoch" given in contest conditions (see extended comment at the beginning of the SC code file), but from the "loads new epoch parameters (validators)" text in contest task definition, it can be inferred that epoch is solely defined by the validator set (keyblock chain is required only for newKeyBlock).

⚠️ Moreover, "Block in check_block message may have all unused branches pruned." - there may be not enough information to even check the "current or future" epoch relation - and by this condition we are obliged to accept blocks with pruned block header!

πŸ›‘οΈ Nevertheless, I leave this to discretion of contract user, they may use more secure "pedantic" mode that strictly requires block relation to the keyblock, or utilize more "relaxed" mode where only signatures are checked.
Good job on the submission! The code looks solid and the comments make it clear it's well thought through!

I think it's OK security-wise. Couple of notes:

1. I do think the pedantic mode is required, because when verifying a block in a future epoch, the stored validator weights are not valid anymore and it's impossible to know if the signatures add up to a majority in that future block's epoch
2. I wouldn't send a merkle proof with just a single pruned branch. From a security perspective, it doesn't do more than sending the same hash twice
3. I wonder why tracking state in a hashmap would be "morally forbidden"? Is it not possible to create this without leaks through limits, bounced messages and gas checking?
Shiny Giraffe Feb 10 at 09:17
πŸ‘‹ Hi, thanks for stopping by and taking a look!

πŸ“£ I got quite a bit to say on this topic, therefore, please, take a look at the attached picture for the full message!

🧐 1. Yeah, I think so too, while there are no practical reasons to lower security, pedantic mode with tighter checks would contradict some contest conditions we are obliged to comply with (header may be pruned and epoch may be implied only by validators - see more details in attached picture πŸ–ΌοΈ).

☝️ 2. Well, that depends on user, but because of condition mentioned above I chose to optimize it to the max and send a proof this way - security wise it does not differ from single cell with 4 pruned refs.

πŸ€” 3. There are several implications when using hashmaps, and I explained them througtly in the attached picture πŸ–ΌοΈ.
πŸ”— For your convenience, a clickable link for point d): https://t.me/tonstatus/88
Nobody added any issues yet...