-
Notifications
You must be signed in to change notification settings - Fork 705
Description
Is your feature request related to a problem? Please describe.
Post-conditions are great to minimize (eliminate) damage that can be made to user or contract assets. However there are cases where one change in contract variable or map can be equally detrimental.
Let's take a look at simple example. We have a contract from which only current owner
is able to transfer funds, and he can also designate new owner.
(define-constant CONTRACT_ADDRESS (as-contract tx-sender))
(define-constant ERR_NOT_AUTHORIZED (err u1001))
(define-data-var owner principal tx-sender)
(define-public (transfer-funds (amount uint) (recipient principal))
(begin
(asserts! (is-eq contract-caller (var-get owner)) ERR_NOT_AUTHORIZED)
(as-contract (stx-transfer? amount CONTRACT_ADDRESS recipient))
)
)
(define-public (change-owner (newOwner principal))
(begin
(asserts! (is-eq tx-sender (var-get owner)) ERR_NOT_AUTHORIZED)
(ok (var-set owner newOwner))
)
)
At first glance change-owner
function appears to be secured correctly. But it's a false impression. Securing functions with just tx-sender
makes contract susceptible to attacks in which we'll be convinced to buy a popular NFT or interact with any potentially harmless contract with masked contract call to our contract.
We can of course replace tx-sender
with contract-caller
- just like it has been done in transfer-funds
function, but this close the possibility to make multiple changes in one TX via proxy contract.
Describe the solution you'd like
I'd like to have an additional post-condition, that would protect users from calling unknowingly functions they do not want to call.
Specifying whole call chain in post-conditions would be an insane idea, therefore I think all functions which developers want to protect with post-condition could be marked with dedicated annotation or they should call some new, native clarity function eg. guard-with-post-condition
.
Describe alternatives you've considered
I came up with the idea that we can use existing post-conditions to secure this type of functions.
All we have to do is transfer 1 micro STX in each fragile function. It works but it is a very hack-ish way to secure contract.
Wallets could also show potential execution path (which functions will be called or can be called by our TX) before user sign and submit TX. However for most users probably it would be overwhelming and very technical and they would just skip it without paying any attention to it.
Additional context
https://app.sigle.io/friedger.id/HuOT9tNQC8fTXOsK28D7e