零碎的Solidity小测验.01

本系列题目出自推特博主@the_ethernaut系列推特。 本人是在准备面试过程中,总结一些有意思的题目。
本文永久链接:https://learnblockchain.cn/article/3845

  1. How would you call a function on a third party contract B, on behalf of the sender, through your contract A, guaranteeing no reverts?

题目意思就是如何通过合约A代表发送者调用合约B的函数,答案很简单咯,就是delegatecall

contract B{
    uint value;
    function test(){
        value = 10;
    }
}

contract A{
    function _delegate(address _B){
        (bool suc,) = _B.delegatecall(abi.encodeWithSignature("test"));
        require(suc, "delegate call failed");
    }
}

  1. What’s the main difference between a transparent proxy and a universal proxy?

题目意思是透明合约和代理合约的主要区别是啥?社区里这篇文章很详细的介绍了这俩代理模式的。可以瞅一瞅。

contract TransparentProxy{
    uint public value;
    address public implementation;
    address public owner;
    constructor(address _v1){
        implementation = _v1;
        owner = msg.sender;
    }
    modifier onlyOwner(){
        require(msg.sender == owner, "only owner");
        _;
    }
    function _upgrade(address _newImplementation) public onlyOwner{
        implementation = _newImplementation;
    }

    function _delegatecall() public {
        (bool suc,) = implementation.delegatecall(msg.data);
        require(suc, "delegatecall failed");
    }
}

contract BoxV1{
    uint public value;
    function set(uint _value) public{
        value = _value;
    }
}
contract UniversalProxy{
    uint public value;
    address public implementation;
    constructor(address _v1){
        implementation = _v1;

    }   
    function _delegatecall() public {
        (bool suc,) = implementation.delegatecall(msg.data);
        require(suc, "delegatecall failed");
    }
}

abstract contract Box{
    uint public value;
    address public implementation;
    address public owner ;
    modifier onlyOwner(){
        require(msg.sender == owner, "only owner");
        _;
    }
    function _upgrade(address _newimplementation) public onlyOwner {
        implementation = _newimplementation;
    }
}
contract BoxV1 is Box{
    function set(uint _value) public {
        value = _value;
    }
}

参考答案:

通用代理优势:通过在实现合约上定义所有函数,它可以依靠Solidity编译器检查任何函数选择器冲突。此外,通用代理的大小要小得多,从而使部署更便宜。在每次调用中,从存储中需要读取的内容更少,降低了开销。 通用代理劣势:如果一次合约忘记写upgrade函数,将会永远无法升级了。


  1. How could you destroy the implementation of, and effectively brick, a universal proxy? Assumptions:
  • You re not the owner of the proxy
  • No one owns the implementation
  • The implementation uses delegatecall to guarantee that the next implementation is not sterile

题目大概意思是,你怎么能破坏通用代理的实现合约,并有效地将其变成砖头(废弃)?条件如下:

  • 你不是代理合约的owner
  • 没人是implementation合约的owner
  • implementation合约使用了delegatecall去保证每个implementation合约总是可升级的(可以看上面的通用代理劣势)

参考答案:因为implementation合约里有调用delegatecall,去调用别的合约,那只要在该合约中加一个selfdestruct函数,即可完成对通用代理的毁灭。所以在implementation合约里最好不要使用selfdestruct和delegatecall函数。详细可以查看这篇文档

点赞 1
收藏 2
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

1 条评论

请先 登录 后评论
shenstone.eth
shenstone.eth
0xD708...4832
如果你喜欢我的文章(翻译or原创),可以请我喝杯咖啡,谢谢:) ens:shenstone.eth