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
溢出有关
大概两个合约相当于两个类?,那么
setTime
函数在这里是干嘛的
在Remix IDE里调用函数的结果是测试性的?(未写入区块或未连接合约地址?)
1
liangdu 2018-12-16 01:38:53 +08:00 via Android
capturetheflag 的约束在 request 写着了,合约的发起者必须是 owner,owner 通常在初始化的时候设置,你的代码不全,看不出完整业务场景。就你给出的代码来讲,settime 就是给 preservation 合约实例的 librarycontract 成员设置属性值而已,settime 可以破例看做成员方法(ps:智能合约的设计思想不能和面向对象一概而论)
|
2
liangdu 2018-12-16 01:46:18 +08:00 via Android 2
这贴好冷门,答漏了
remix 是通过跟本地的测试节点进程交互(js 调用 rpc 接口通讯),实现高仿真测试。实际上可以理解为就是生产了,只是没有和公链一个网络。 但是测试结果准确性不能证明在它的派生链也有效,比如基于 eth 拓展的 quorum 框架,虽然都是 eth 虚拟机,但是有些兼容问题。 |
3
zsszuh 2018-12-16 01:49:02 +08:00 via Android 1
谁知道以太币怎么造的?😂
|
4
whoami9894 OP @liangdu
感谢回复,确实冷门←_←,原来都没听说过 solidity。还想请问一下: capturetheflag 的 owner 是理解为合约的创造者==消息的发送者吗。这里需要以自己的邮箱为参数调用 capturetheflag 来获得 flag,但我调用了好像没有什么用,remix 里也没有报错信息(可能是我没看到) 这个合约无法查看 abi(和我看别人的项目不太一样),且合约地址的 code 里有类似汇编的代码,那个是可以反编译生成完整代码的吗。题目给了一个 sol 文件就是我贴上的,还有一个合约地址,如果按您说的代码不全可能需要从操作码反编译?(或者合约没有开源) |
5
Hconk 2018-12-16 10:00:08 +08:00 via Android 1
根据代码,owner 是你在创建合约时的发送人,有些合约提供了修改 owner 的功能,这样的合约 owner 就不一定是合约的发布者了。msg.sender 是你调用这个合约时使用的地址。
timeZone1Library 和 timeZone2Library 是另外两个合约的地址,settime 具体什么功能是业务相关的,要看另外两个合约怎么写,这里应该可以理解为 c++里面的前置声明,用于在这个合约上的调用外部的函数。 |
6
whoami9894 OP @Hconk
感谢回复 是不是在构造函数里修改了 own 地址为 msg.sender,这里的 time1 和 time2 是两个合约地址,我可以填入自己的合约代码然后 delegatecall 调用是吗(不知道理解的对不对) 还有就是我调用 capturetheflag 不知道为什么没有写入`ropsten.etherscan.io/0x_______`的 event 中 |
7
Hconk 2018-12-16 10:35:34 +08:00 via Android
@whoami9894 构造函数肯定只在发布合约时会调用一次,调用时的 msg.sender 就是合约创建者。
两个合约地址也是初始化时候填写的地址,是通过 delegatecall 去调用这两个合约的 settime 方法。 remix 编译器需要选择使用哪个网络,有本地浏览器上的 vm,还有 mainnet,或者自定义,不知道你有没有选对。你先查看你那个地址的有没有交易记录,再看交易的详情 data 数据有没有问题。 |
8
liangdu 2018-12-16 10:57:54 +08:00 via Android
我通常用 nodejs 配合 truffle test 来测试智能合约,通过 web3 接口可以监听到合约的事件(事务被打包时抛出)。remix 没怎么用,因为当时需要做测试驱动开发,用 remix 不适合。你也可以不监听,truffle 在 test 报错的时候会列出所有合约抛出的 event
在代码最后加上 assert(false)就可以人为制造错误了 |
9
whoami9894 OP @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/ |
10
whoami9894 OP @Hconk
@liangdu ![]( https://upload-images.jianshu.io/upload_images/11356161-30b8aba42e7fabda.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) ![]( https://upload-images.jianshu.io/upload_images/11356161-78ad090a02535efa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 我已经把 owner 地址修改为我 account 地址了,可是 debug 依旧在`require (owner == msg.sender);`那里报错 |
11
liangdu 2018-12-16 11:56:25 +08:00 via Android
哈啊哈,不对,account 不是你理解的邮箱地址,而且钱包地址。也就外部地址。
你可以提供更多你的资料,比如报错信息,放在 v2ex。 |
12
imgode 2018-12-16 12:05:11 +08:00 via Android
owner 是这个合约的部署者,msg.sender 是这个方法的调用者,require 是相当于一个判断,合约的部署者和调用者一致才往下执行,否则抛出异常,一般会写一个 modifier 来修饰这个函数而不是用 require 这样
|
13
imgode 2018-12-16 12:08:50 +08:00 via Android
部署合约的时候会调用 constructor 构造函数,构造函数里写了 owner=msg.sender 所以你这个合约的拥有者也就是 owner 就是你部署合约的那个账户,在调用下面的方法的时候,同样用你部署合约那个账户调用即可,setTime 就是给一个状态变量赋值
|
14
whoami9894 OP |
15
whoami9894 OP @liangdu
绕晕了,我的 account 地址是 remix 右上角的 0xca35b7d915458ef540ade6068dfe2f44e8fa733c 那个吗。 好像没有友好的报错信息,我是在 remix 的 debugger 里看到 require 那一行标红了 |