The s_password
variable is expected to be only known by the owner, however, anyone can read the password directly from the contract's storage.
The string private s_password
variable is expected to be only known by the owner of the contract, but private variables can be accessed in multiple different ways by accessing the storage slot the variables are stored in.
Here you can see the NatSpec above the contract that states "others won't be able to see" your password:
Here is a test easily showing that we can view the password by accessing PasswordStore
's first storage slot. For emphasis, we even do so from address(1)
.
In this test, we first set the password to "Froggy", then using Foundry's vm.load()
we store the data at PasswordStore
's first storage slot in a variable called data
. We can't directly compare the data to the newPassword
string because of how Solidity stores dynamic variables, so before that we will cast both the newPassword
and the data
variables into bytes
. After we create the two bytes
variables, all that's left to do is remove the extra hex digits, such as padding and the string's length, from our loadedBytes
object. To do so we use a simple for
loop that creates a temporary trimmedBytes
variable that contains all the loadedBytes
data up until the length of loadedBytes
is equal to expectedBytes
, then we set loadedBytes
equal to trimmedBytes
, essentially updating the variable to exclude the extra hex digits we don't care about.
Finally, we use Foundry's assertEq()
function to ensure that loadedBytes
cast as a string is equal to newPassword
.
This completely undermines the intentions of the developer and leaves the contract unusable if you truly care about the password being known by only the contract's owner.
Manual review
I recommend the developers entirely rethink their project and restructure it without trying to implement any sort of on-chain password since anything on the blockchain is publicly available for all to see. If you really must store a password in a smart contract, you need to hash/encode it before storing it, this way when anyone reads the variable from storage, they will only see the password's hash. One way to do so would be to use a one-way hashing algorithm such as SHA-256, just remember to never include the actual password in a blockchain transaction, or else it will be exposed forever.
Private functions and state variables are only visible for the contract they are defined in and not in derived contracts. In this case private doesn't mean secret/confidential
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.