想请教一个 solidity 以太坊合约的代码问题

2018-12-15 23:37:19 +08:00
 whoami9894
pragma solidity ^0.4.23;

contract Preservation {

  // public library contracts 
  address public timeZone1Library;
  address public timeZone2Library;
  address public owner; 
  uint storedTime;
  // Sets the function signature for delegatecall
  bytes4 constant setTimeSignature = bytes4(keccak256("setTime(uint256)"));

  event FLAG(string b64email, string slogan);

  constructor(address _timeZone1LibraryAddress, address _timeZone2LibraryAddress) public {
    timeZone1Library = _timeZone1LibraryAddress; 
    timeZone2Library = _timeZone2LibraryAddress; 
    owner = msg.sender;
  }

  // set the time for timezone 1
  function setFirstTime(uint _timeStamp) public {
    timeZone1Library.delegatecall(setTimeSignature, _timeStamp);
  }

  // set the time for timezone 2
  function setSecondTime(uint _timeStamp) public {
    timeZone2Library.delegatecall(setTimeSignature, _timeStamp);
  }

  function CaptureTheFlag(string b64email) public{
    require (owner == msg.sender);
    emit FLAG(b64email, "Congratulations to capture the flag!");
  }
}

// Simple library contract to set the time
contract LibraryContract {

  // stores a timestamp 
  uint storedTime;  

  function setTime(uint _time) public {
    storedTime = _time;
  }
}

对以太坊相关一窍不通,看了不少文章还是有点摸不着头脑....

这是区块链安全想关的,想请教一下这段合约代码放在 Remix 上编译运行后调用CaptureTheFlag函数前有什么约束吗(这里的目的是调用该函数),我的猜想这里时间戳可能与uint256溢出有关

3507 次点击
所在节点    Solidity
15 条回复
liangdu
2018-12-16 01:38:53 +08:00
capturetheflag 的约束在 request 写着了,合约的发起者必须是 owner,owner 通常在初始化的时候设置,你的代码不全,看不出完整业务场景。就你给出的代码来讲,settime 就是给 preservation 合约实例的 librarycontract 成员设置属性值而已,settime 可以破例看做成员方法(ps:智能合约的设计思想不能和面向对象一概而论)
liangdu
2018-12-16 01:46:18 +08:00
这贴好冷门,答漏了

remix 是通过跟本地的测试节点进程交互(js 调用 rpc 接口通讯),实现高仿真测试。实际上可以理解为就是生产了,只是没有和公链一个网络。

但是测试结果准确性不能证明在它的派生链也有效,比如基于 eth 拓展的 quorum 框架,虽然都是 eth 虚拟机,但是有些兼容问题。
zsszuh
2018-12-16 01:49:02 +08:00
谁知道以太币怎么造的?😂
whoami9894
2018-12-16 08:47:52 +08:00
@liangdu

感谢回复,确实冷门←_←,原来都没听说过 solidity。还想请问一下:

capturetheflag 的 owner 是理解为合约的创造者==消息的发送者吗。这里需要以自己的邮箱为参数调用 capturetheflag 来获得 flag,但我调用了好像没有什么用,remix 里也没有报错信息(可能是我没看到)

这个合约无法查看 abi(和我看别人的项目不太一样),且合约地址的 code 里有类似汇编的代码,那个是可以反编译生成完整代码的吗。题目给了一个 sol 文件就是我贴上的,还有一个合约地址,如果按您说的代码不全可能需要从操作码反编译?(或者合约没有开源)
Hconk
2018-12-16 10:00:08 +08:00
根据代码,owner 是你在创建合约时的发送人,有些合约提供了修改 owner 的功能,这样的合约 owner 就不一定是合约的发布者了。msg.sender 是你调用这个合约时使用的地址。

timeZone1Library 和 timeZone2Library 是另外两个合约的地址,settime 具体什么功能是业务相关的,要看另外两个合约怎么写,这里应该可以理解为 c++里面的前置声明,用于在这个合约上的调用外部的函数。
whoami9894
2018-12-16 10:18:16 +08:00
@Hconk

感谢回复

是不是在构造函数里修改了 own 地址为 msg.sender,这里的 time1 和 time2 是两个合约地址,我可以填入自己的合约代码然后 delegatecall 调用是吗(不知道理解的对不对)

还有就是我调用 capturetheflag 不知道为什么没有写入`ropsten.etherscan.io/0x_______`的 event 中
Hconk
2018-12-16 10:35:34 +08:00
@whoami9894 构造函数肯定只在发布合约时会调用一次,调用时的 msg.sender 就是合约创建者。

两个合约地址也是初始化时候填写的地址,是通过 delegatecall 去调用这两个合约的 settime 方法。

remix 编译器需要选择使用哪个网络,有本地浏览器上的 vm,还有 mainnet,或者自定义,不知道你有没有选对。你先查看你那个地址的有没有交易记录,再看交易的详情 data 数据有没有问题。
liangdu
2018-12-16 10:57:54 +08:00
我通常用 nodejs 配合 truffle test 来测试智能合约,通过 web3 接口可以监听到合约的事件(事务被打包时抛出)。remix 没怎么用,因为当时需要做测试驱动开发,用 remix 不适合。你也可以不监听,truffle 在 test 报错的时候会列出所有合约抛出的 event

在代码最后加上 assert(false)就可以人为制造错误了
whoami9894
2018-12-16 11:25:13 +08:00
@Hconk
@liangdu

我 Google 出了这道题的解法:是 delegatecall 函数的漏洞来恶意修改 owner,可是我在按题解测试的时候依旧死在`require (owner == msg.sender);`

http://www.bendawang.site/2018/11/13/Zeppelin-ethernaut-writeup/#Preservation-X

https://blog.riskivy.com/智能合约 ctf:ethernaut-writeup-part-4/
whoami9894
2018-12-16 11:48:42 +08:00
liangdu
2018-12-16 11:56:25 +08:00
哈啊哈,不对,account 不是你理解的邮箱地址,而且钱包地址。也就外部地址。


你可以提供更多你的资料,比如报错信息,放在 v2ex。
imgode
2018-12-16 12:05:11 +08:00
owner 是这个合约的部署者,msg.sender 是这个方法的调用者,require 是相当于一个判断,合约的部署者和调用者一致才往下执行,否则抛出异常,一般会写一个 modifier 来修饰这个函数而不是用 require 这样
imgode
2018-12-16 12:08:50 +08:00
部署合约的时候会调用 constructor 构造函数,构造函数里写了 owner=msg.sender 所以你这个合约的拥有者也就是 owner 就是你部署合约的那个账户,在调用下面的方法的时候,同样用你部署合约那个账户调用即可,setTime 就是给一个状态变量赋值
whoami9894
2018-12-16 12:14:07 +08:00
@imgode

可是我的函数依旧卡在 require 的判断

可能我理解有误,我在 remix 里构建实例并且获得了一个地址是部署吗
whoami9894
2018-12-16 12:18:08 +08:00
@liangdu

绕晕了,我的 account 地址是 remix 右上角的 0xca35b7d915458ef540ade6068dfe2f44e8fa733c 那个吗。

好像没有友好的报错信息,我是在 remix 的 debugger 里看到 require 那一行标红了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/517929

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX