Fix/pox5 contract reentrancy#7239
Conversation
Coverage Report for CI Build 26643304473Warning Build has drifted: This PR's base is out of sync with its target branch, so coverage data may include unrelated changes. Coverage increased (+0.06%) to 86.017%Details
Uncovered ChangesNo uncovered changes found. Coverage Regressions6298 previously-covered lines in 90 files lost coverage.
Coverage Stats
💛 - Coveralls |
| // ERR_REENTRANT_CALL = (err u46) — clarigen types must be regenerated after patch | ||
| const ERR_REENTRANT_CALL = 46n; |
There was a problem hiding this comment.
Can you run npx clarigen in contrib/core-contract-tests? You can also run npx clarigen -w to keep it running in watch mode.
There was a problem hiding this comment.
You will need to upgrade the clarigen packages in package.json to 4.1.6.
There was a problem hiding this comment.
@brice-stacks is it the reason why it failed and i needed to fix it manually?
|
|
||
| ;; Call `old-signer-manager`, and allow them to snapshot current | ||
| ;; data before updating. Do not throw any errors. | ||
| (match (contract-call? old-signer-manager checkpoint-staker staker bond-index u1 |
There was a problem hiding this comment.
There's no guard around this trait call.
| (asserts! (is-eq (contract-of signer-manager) signer) | ||
| ERR_INVALID_OLD_SIGNER_MANAGER | ||
| ) | ||
| (begin |
There was a problem hiding this comment.
This begin is unnecessary.
| (try! (validate-no-reentrancy)) | ||
| (var-set signer-manager-call-active true) | ||
| (try! (contract-call? signer-manager validate-stake! tx-sender bond-index u1 | ||
| amount-ustx sats-total true signer-calldata | ||
| )) | ||
| (var-set signer-manager-call-active false) |
There was a problem hiding this comment.
What do you think about putting all calls to the traits inside a private function that does the `var-sets for you? It would be nice if we supporter lambda expressions so it could be generic, but without that, I think we'd need a private function for each trait function we call, so just 2 I think. My worry is that it is easy to forget to do this. Having a private function doesn't force us to use it, but it does ensure that if it is used, we do the var setting correctly.
So one function for example would look like this:
(define-private (guarded-validate-stake?
(signer-manager <signer-manager-trait>)
(staker principal)
(first-index uint)
(num-indexes uint)
(amount-ustx uint)
(amount-sats uint)
(is-bond bool)
(signer-calldata (optional (buff 500)))
)
(begin
(var-set signer-manager-call-active true)
(let ((result (contract-call? signer-manager validate-stake! staker first-index
num-indexes amount-ustx amount-sats is-bond signer-calldata
)))
(var-set signer-manager-call-active false)
result
)
)
)Do others think that would be worthwhile? Any ideas for a better solution.
Description
This patch ensures no re-entrancy is used (abused) during pox-5 contract function calls.
A new error code ERR_REENTRANT_CALL has been added too.
Applicable issues
Additional info (benefits, drawbacks, caveats)
Checklist
docs/property-testing.md)changelog.d/README.md)rpc/openapi.yamlfor RPC endpoints,event-dispatcher.mdfor new events)clarity-benchmarkingrepo