Bug Bounty - Initialize Function Calls [Smart Contracts/DVM]

Bug Bounty - Initialize Function Calls [Smart Contracts/DVM]

We wanted to inform community developers about a smart contract bug that could be exploited in certain smart contracts. In short, the bug was reported, a reward will be issued, and the solutions are listed below.

Issue

The Initialize() and InitializePrivate() functions within a smart contract can be called after deploying the smart contract. This is required behavior for subsequent UpdateCode() functions that allow the updated smart contract code to reinitialize. However, if the smart contract author uses Signer() to assign the contract owner within the function, anyone calling an initialize function will be added as the new contract owner.

Solution

The solution comes in two parts. First, smart contract authors should hardcode their intended address for contract ownership, then add a check within the Initialize() or InitializePrivate() functions to ensure that the caller is the true owner.

Example

Function Initialize() Uint64 
  10 IF SIGNER() == address_raw("deto1qy0ehnqjpr0wxqnknyc66du2fsxyktppkr8m8e6jvplp954klfjz2qqdzcd8p") THEN 
  GOTO 30 
  20 RETURN 0 // exit 
  30 // continue contract logic
  40 RETURN 0 
End Function

A solution within the DVM will be added in the next release that will add more checks to help prevent such issues, but it is still recommended to use the above solution within any smart contracts.

A bounty will be awarded to the tester and we will provide more details about the added DVM changes closer to the next release. Thank you for your continued support and to all of the testers and builders in our community.

4 Likes

Another point to add is Initialize() and InitializePrivate() are also callable from other functions, providing the above resolution as important as well to handle for such things:

Function Initialize() Uint64
    10  STORE("owner", SIGNER())
    20  RETURN 0
End Function

Function Test() Uint64
    10  Initialize()
    20  RETURN 0
End Function

Another resolution that has been discussed at length through our dApps community as well is something along the lines like:

Function Initialize() Uint64
    10  IF EXISTS("owner") == 0 THEN GOTO 30
    20  RETURN 1 // exit
    30  // continue contract logic
    40  RETURN 0
End Function

Both resolutions could be of value depending on what you are needing to accomplish, whether or not you leverage(d) the Initialize function to reset variables or other situations. Be sure to analyze/address your contracts and test accordingly through testnet to ensure code coverage. And as stated, we will await the next update for more details.

2 Likes