Add SB Curated (copied from the smartbugs repository).
This commit is contained in:
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 54
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract PERSONAL_BANK
|
||||
{
|
||||
mapping (address=>uint256) public balances;
|
||||
|
||||
uint public MinSum = 1 ether;
|
||||
|
||||
LogFile Log = LogFile(0x0486cF65A2F2F3A392CBEa398AFB7F5f0B72FF46);
|
||||
|
||||
bool intitalized;
|
||||
|
||||
function SetMinSum(uint _val)
|
||||
public
|
||||
{
|
||||
if(intitalized)revert();
|
||||
MinSum = _val;
|
||||
}
|
||||
|
||||
function SetLogFile(address _log)
|
||||
public
|
||||
{
|
||||
if(intitalized)revert();
|
||||
Log = LogFile(_log);
|
||||
}
|
||||
|
||||
function Initialized()
|
||||
public
|
||||
{
|
||||
intitalized = true;
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
balances[msg.sender]+= msg.value;
|
||||
Log.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(balances[msg.sender]>=MinSum && balances[msg.sender]>=_am)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
Log.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Deposit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
contract LogFile
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 38
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract PrivateBank
|
||||
{
|
||||
mapping (address => uint) public balances;
|
||||
|
||||
uint public MinDeposit = 1 ether;
|
||||
|
||||
Log TransferLog;
|
||||
|
||||
function PrivateBank(address _log)
|
||||
{
|
||||
TransferLog = Log(_log);
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(msg.value >= MinDeposit)
|
||||
{
|
||||
balances[msg.sender]+=msg.value;
|
||||
TransferLog.AddMessage(msg.sender,msg.value,"Deposit");
|
||||
}
|
||||
}
|
||||
|
||||
function CashOut(uint _am)
|
||||
{
|
||||
if(_am<=balances[msg.sender])
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
TransferLog.AddMessage(msg.sender,_am,"CashOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable{}
|
||||
|
||||
}
|
||||
|
||||
contract Log
|
||||
{
|
||||
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 55
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract ACCURAL_DEPOSIT
|
||||
{
|
||||
mapping (address=>uint256) public balances;
|
||||
|
||||
uint public MinSum = 1 ether;
|
||||
|
||||
LogFile Log = LogFile(0x0486cF65A2F2F3A392CBEa398AFB7F5f0B72FF46);
|
||||
|
||||
bool intitalized;
|
||||
|
||||
function SetMinSum(uint _val)
|
||||
public
|
||||
{
|
||||
if(intitalized)revert();
|
||||
MinSum = _val;
|
||||
}
|
||||
|
||||
function SetLogFile(address _log)
|
||||
public
|
||||
{
|
||||
if(intitalized)revert();
|
||||
Log = LogFile(_log);
|
||||
}
|
||||
|
||||
function Initialized()
|
||||
public
|
||||
{
|
||||
intitalized = true;
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
balances[msg.sender]+= msg.value;
|
||||
Log.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(balances[msg.sender]>=MinSum && balances[msg.sender]>=_am)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
Log.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Deposit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
contract LogFile
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 54
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract PRIVATE_ETH_CELL
|
||||
{
|
||||
mapping (address=>uint256) public balances;
|
||||
|
||||
uint public MinSum;
|
||||
|
||||
LogFile Log;
|
||||
|
||||
bool intitalized;
|
||||
|
||||
function SetMinSum(uint _val)
|
||||
public
|
||||
{
|
||||
require(!intitalized);
|
||||
MinSum = _val;
|
||||
}
|
||||
|
||||
function SetLogFile(address _log)
|
||||
public
|
||||
{
|
||||
require(!intitalized);
|
||||
Log = LogFile(_log);
|
||||
}
|
||||
|
||||
function Initialized()
|
||||
public
|
||||
{
|
||||
intitalized = true;
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
balances[msg.sender]+= msg.value;
|
||||
Log.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(balances[msg.sender]>=MinSum && balances[msg.sender]>=_am)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
Log.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Deposit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
contract LogFile
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 54
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract BANK_SAFE
|
||||
{
|
||||
mapping (address=>uint256) public balances;
|
||||
|
||||
uint public MinSum;
|
||||
|
||||
LogFile Log;
|
||||
|
||||
bool intitalized;
|
||||
|
||||
function SetMinSum(uint _val)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
MinSum = _val;
|
||||
}
|
||||
|
||||
function SetLogFile(address _log)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
Log = LogFile(_log);
|
||||
}
|
||||
|
||||
function Initialized()
|
||||
public
|
||||
{
|
||||
intitalized = true;
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
balances[msg.sender]+= msg.value;
|
||||
Log.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(balances[msg.sender]>=MinSum && balances[msg.sender]>=_am)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
Log.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Deposit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
contract LogFile
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 94
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract Ownable
|
||||
{
|
||||
address newOwner;
|
||||
address owner = msg.sender;
|
||||
|
||||
function changeOwner(address addr)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
newOwner = addr;
|
||||
}
|
||||
|
||||
function confirmOwner()
|
||||
public
|
||||
{
|
||||
if(msg.sender==newOwner)
|
||||
{
|
||||
owner=newOwner;
|
||||
}
|
||||
}
|
||||
|
||||
modifier onlyOwner
|
||||
{
|
||||
if(owner == msg.sender)_;
|
||||
}
|
||||
}
|
||||
|
||||
contract Token is Ownable
|
||||
{
|
||||
address owner = msg.sender;
|
||||
function WithdrawToken(address token, uint256 amount,address to)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
token.call(bytes4(sha3("transfer(address,uint256)")),to,amount);
|
||||
}
|
||||
}
|
||||
|
||||
contract TokenBank is Token
|
||||
{
|
||||
uint public MinDeposit;
|
||||
mapping (address => uint) public Holders;
|
||||
|
||||
///Constructor
|
||||
function initTokenBank()
|
||||
public
|
||||
{
|
||||
owner = msg.sender;
|
||||
MinDeposit = 1 ether;
|
||||
}
|
||||
|
||||
function()
|
||||
payable
|
||||
{
|
||||
Deposit();
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
payable
|
||||
{
|
||||
if(msg.value>MinDeposit)
|
||||
{
|
||||
Holders[msg.sender]+=msg.value;
|
||||
}
|
||||
}
|
||||
|
||||
function WitdrawTokenToHolder(address _to,address _token,uint _amount)
|
||||
public
|
||||
onlyOwner
|
||||
{
|
||||
if(Holders[_to]>0)
|
||||
{
|
||||
Holders[_to]=0;
|
||||
WithdrawToken(_token,_amount,_to);
|
||||
}
|
||||
}
|
||||
|
||||
function WithdrawToHolder(address _addr, uint _wei)
|
||||
public
|
||||
onlyOwner
|
||||
payable
|
||||
{
|
||||
if(Holders[_addr]>0)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(_addr.call.value(_wei)())
|
||||
{
|
||||
Holders[_addr]-=_wei;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 29
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
contract U_BANK
|
||||
{
|
||||
function Put(uint _unlockTime)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
acc.balance += msg.value;
|
||||
acc.unlockTime = _unlockTime>now?_unlockTime:now;
|
||||
LogFile.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
if( acc.balance>=MinSum && acc.balance>=_am && now>acc.unlockTime)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
acc.balance-=_am;
|
||||
LogFile.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Put(0);
|
||||
}
|
||||
|
||||
struct Holder
|
||||
{
|
||||
uint unlockTime;
|
||||
uint balance;
|
||||
}
|
||||
|
||||
mapping (address => Holder) public Acc;
|
||||
|
||||
Log LogFile;
|
||||
|
||||
uint public MinSum = 2 ether;
|
||||
|
||||
function U_BANK(address log) public{
|
||||
LogFile = Log(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract Log
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 52
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract PrivateDeposit
|
||||
{
|
||||
mapping (address => uint) public balances;
|
||||
|
||||
uint public MinDeposit = 1 ether;
|
||||
address public owner;
|
||||
|
||||
Log TransferLog;
|
||||
|
||||
modifier onlyOwner() {
|
||||
require(tx.origin == owner);
|
||||
_;
|
||||
}
|
||||
|
||||
function PrivateDeposit()
|
||||
{
|
||||
owner = msg.sender;
|
||||
TransferLog = new Log();
|
||||
}
|
||||
|
||||
|
||||
|
||||
function setLog(address _lib) onlyOwner
|
||||
{
|
||||
TransferLog = Log(_lib);
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(msg.value >= MinDeposit)
|
||||
{
|
||||
balances[msg.sender]+=msg.value;
|
||||
TransferLog.AddMessage(msg.sender,msg.value,"Deposit");
|
||||
}
|
||||
}
|
||||
|
||||
function CashOut(uint _am)
|
||||
{
|
||||
if(_am<=balances[msg.sender])
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
TransferLog.AddMessage(msg.sender,_am,"CashOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable{}
|
||||
|
||||
}
|
||||
|
||||
contract Log
|
||||
{
|
||||
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 29
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
contract W_WALLET
|
||||
{
|
||||
function Put(uint _unlockTime)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
acc.balance += msg.value;
|
||||
acc.unlockTime = _unlockTime>now?_unlockTime:now;
|
||||
LogFile.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
if( acc.balance>=MinSum && acc.balance>=_am && now>acc.unlockTime)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
acc.balance-=_am;
|
||||
LogFile.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Put(0);
|
||||
}
|
||||
|
||||
struct Holder
|
||||
{
|
||||
uint unlockTime;
|
||||
uint balance;
|
||||
}
|
||||
|
||||
mapping (address => Holder) public Acc;
|
||||
|
||||
Log LogFile;
|
||||
|
||||
uint public MinSum = 1 ether;
|
||||
|
||||
function W_WALLET(address log) public{
|
||||
LogFile = Log(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract Log
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 41
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract ETH_VAULT
|
||||
{
|
||||
mapping (address => uint) public balances;
|
||||
|
||||
Log TransferLog;
|
||||
|
||||
uint public MinDeposit = 1 ether;
|
||||
|
||||
function ETH_VAULT(address _log)
|
||||
public
|
||||
{
|
||||
TransferLog = Log(_log);
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(msg.value > MinDeposit)
|
||||
{
|
||||
balances[msg.sender]+=msg.value;
|
||||
TransferLog.AddMessage(msg.sender,msg.value,"Deposit");
|
||||
}
|
||||
}
|
||||
|
||||
function CashOut(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(_am<=balances[msg.sender])
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
TransferLog.AddMessage(msg.sender,_am,"CashOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable{}
|
||||
|
||||
}
|
||||
|
||||
contract Log
|
||||
{
|
||||
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 29
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
contract X_WALLET
|
||||
{
|
||||
function Put(uint _unlockTime)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
acc.balance += msg.value;
|
||||
acc.unlockTime = _unlockTime>now?_unlockTime:now;
|
||||
LogFile.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
if( acc.balance>=MinSum && acc.balance>=_am && now>acc.unlockTime)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
acc.balance-=_am;
|
||||
LogFile.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Put(0);
|
||||
}
|
||||
|
||||
struct Holder
|
||||
{
|
||||
uint unlockTime;
|
||||
uint balance;
|
||||
}
|
||||
|
||||
mapping (address => Holder) public Acc;
|
||||
|
||||
Log LogFile;
|
||||
|
||||
uint public MinSum = 1 ether;
|
||||
|
||||
function X_WALLET(address log) public{
|
||||
LogFile = Log(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract Log
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 44
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract ETH_FUND
|
||||
{
|
||||
mapping (address => uint) public balances;
|
||||
|
||||
uint public MinDeposit = 1 ether;
|
||||
|
||||
Log TransferLog;
|
||||
|
||||
uint lastBlock;
|
||||
|
||||
function ETH_FUND(address _log)
|
||||
public
|
||||
{
|
||||
TransferLog = Log(_log);
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(msg.value > MinDeposit)
|
||||
{
|
||||
balances[msg.sender]+=msg.value;
|
||||
TransferLog.AddMessage(msg.sender,msg.value,"Deposit");
|
||||
lastBlock = block.number;
|
||||
}
|
||||
}
|
||||
|
||||
function CashOut(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(_am<=balances[msg.sender]&&block.number>lastBlock)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
TransferLog.AddMessage(msg.sender,_am,"CashOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable{}
|
||||
|
||||
}
|
||||
|
||||
contract Log
|
||||
{
|
||||
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 63
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract PENNY_BY_PENNY
|
||||
{
|
||||
struct Holder
|
||||
{
|
||||
uint unlockTime;
|
||||
uint balance;
|
||||
}
|
||||
|
||||
mapping (address => Holder) public Acc;
|
||||
|
||||
uint public MinSum;
|
||||
|
||||
LogFile Log;
|
||||
|
||||
bool intitalized;
|
||||
|
||||
function SetMinSum(uint _val)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
MinSum = _val;
|
||||
}
|
||||
|
||||
function SetLogFile(address _log)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
Log = LogFile(_log);
|
||||
}
|
||||
|
||||
function Initialized()
|
||||
public
|
||||
{
|
||||
intitalized = true;
|
||||
}
|
||||
|
||||
function Put(uint _lockTime)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
acc.balance += msg.value;
|
||||
if(now+_lockTime>acc.unlockTime)acc.unlockTime=now+_lockTime;
|
||||
Log.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
if( acc.balance>=MinSum && acc.balance>=_am && now>acc.unlockTime)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
acc.balance-=_am;
|
||||
Log.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Put(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
contract LogFile
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 54
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract DEP_BANK
|
||||
{
|
||||
mapping (address=>uint256) public balances;
|
||||
|
||||
uint public MinSum;
|
||||
|
||||
LogFile Log;
|
||||
|
||||
bool intitalized;
|
||||
|
||||
function SetMinSum(uint _val)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
MinSum = _val;
|
||||
}
|
||||
|
||||
function SetLogFile(address _log)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
Log = LogFile(_log);
|
||||
}
|
||||
|
||||
function Initialized()
|
||||
public
|
||||
{
|
||||
intitalized = true;
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
balances[msg.sender]+= msg.value;
|
||||
Log.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(balances[msg.sender]>=MinSum && balances[msg.sender]>=_am)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
Log.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Deposit();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
contract LogFile
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 40
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract Private_Bank
|
||||
{
|
||||
mapping (address => uint) public balances;
|
||||
|
||||
uint public MinDeposit = 1 ether;
|
||||
|
||||
Log TransferLog;
|
||||
|
||||
function Private_Bank(address _log)
|
||||
{
|
||||
TransferLog = Log(_log);
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(msg.value > MinDeposit)
|
||||
{
|
||||
balances[msg.sender]+=msg.value;
|
||||
TransferLog.AddMessage(msg.sender,msg.value,"Deposit");
|
||||
}
|
||||
}
|
||||
|
||||
function CashOut(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(_am<=balances[msg.sender])
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
TransferLog.AddMessage(msg.sender,_am,"CashOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable{}
|
||||
|
||||
}
|
||||
|
||||
contract Log
|
||||
{
|
||||
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 38
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract PrivateBank
|
||||
{
|
||||
mapping (address => uint) public balances;
|
||||
|
||||
uint public MinDeposit = 1 ether;
|
||||
|
||||
Log TransferLog;
|
||||
|
||||
function PrivateBank(address _lib)
|
||||
{
|
||||
TransferLog = Log(_lib);
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(msg.value >= MinDeposit)
|
||||
{
|
||||
balances[msg.sender]+=msg.value;
|
||||
TransferLog.AddMessage(msg.sender,msg.value,"Deposit");
|
||||
}
|
||||
}
|
||||
|
||||
function CashOut(uint _am)
|
||||
{
|
||||
if(_am<=balances[msg.sender])
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
TransferLog.AddMessage(msg.sender,_am,"CashOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable{}
|
||||
|
||||
}
|
||||
|
||||
contract Log
|
||||
{
|
||||
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 41
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract ETH_VAULT
|
||||
{
|
||||
mapping (address => uint) public balances;
|
||||
|
||||
uint public MinDeposit = 1 ether;
|
||||
|
||||
Log TransferLog;
|
||||
|
||||
function ETH_VAULT(address _log)
|
||||
public
|
||||
{
|
||||
TransferLog = Log(_log);
|
||||
}
|
||||
|
||||
function Deposit()
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(msg.value > MinDeposit)
|
||||
{
|
||||
balances[msg.sender]+=msg.value;
|
||||
TransferLog.AddMessage(msg.sender,msg.value,"Deposit");
|
||||
}
|
||||
}
|
||||
|
||||
function CashOut(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
if(_am<=balances[msg.sender])
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
balances[msg.sender]-=_am;
|
||||
TransferLog.AddMessage(msg.sender,_am,"CashOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable{}
|
||||
|
||||
}
|
||||
|
||||
contract Log
|
||||
{
|
||||
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 63
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract MONEY_BOX
|
||||
{
|
||||
struct Holder
|
||||
{
|
||||
uint unlockTime;
|
||||
uint balance;
|
||||
}
|
||||
|
||||
mapping (address => Holder) public Acc;
|
||||
|
||||
uint public MinSum;
|
||||
|
||||
Log LogFile;
|
||||
|
||||
bool intitalized;
|
||||
|
||||
function SetMinSum(uint _val)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
MinSum = _val;
|
||||
}
|
||||
|
||||
function SetLogFile(address _log)
|
||||
public
|
||||
{
|
||||
if(intitalized)throw;
|
||||
LogFile = Log(_log);
|
||||
}
|
||||
|
||||
function Initialized()
|
||||
public
|
||||
{
|
||||
intitalized = true;
|
||||
}
|
||||
|
||||
function Put(uint _lockTime)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
acc.balance += msg.value;
|
||||
if(now+_lockTime>acc.unlockTime)acc.unlockTime=now+_lockTime;
|
||||
LogFile.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
if( acc.balance>=MinSum && acc.balance>=_am && now>acc.unlockTime)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
acc.balance-=_am;
|
||||
LogFile.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Put(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
contract Log
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 29
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
contract WALLET
|
||||
{
|
||||
function Put(uint _unlockTime)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
acc.balance += msg.value;
|
||||
acc.unlockTime = _unlockTime>now?_unlockTime:now;
|
||||
LogFile.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
if( acc.balance>=MinSum && acc.balance>=_am && now>acc.unlockTime)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
acc.balance-=_am;
|
||||
LogFile.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Put(0);
|
||||
}
|
||||
|
||||
struct Holder
|
||||
{
|
||||
uint unlockTime;
|
||||
uint balance;
|
||||
}
|
||||
|
||||
mapping (address => Holder) public Acc;
|
||||
|
||||
Log LogFile;
|
||||
|
||||
uint public MinSum = 1 ether;
|
||||
|
||||
function WALLET(address log) public{
|
||||
LogFile = Log(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract Log
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* @source: etherscan.io
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 29
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.25;
|
||||
|
||||
contract MY_BANK
|
||||
{
|
||||
function Put(uint _unlockTime)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
acc.balance += msg.value;
|
||||
acc.unlockTime = _unlockTime>now?_unlockTime:now;
|
||||
LogFile.AddMessage(msg.sender,msg.value,"Put");
|
||||
}
|
||||
|
||||
function Collect(uint _am)
|
||||
public
|
||||
payable
|
||||
{
|
||||
var acc = Acc[msg.sender];
|
||||
if( acc.balance>=MinSum && acc.balance>=_am && now>acc.unlockTime)
|
||||
{
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_am)())
|
||||
{
|
||||
acc.balance-=_am;
|
||||
LogFile.AddMessage(msg.sender,_am,"Collect");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function()
|
||||
public
|
||||
payable
|
||||
{
|
||||
Put(0);
|
||||
}
|
||||
|
||||
struct Holder
|
||||
{
|
||||
uint unlockTime;
|
||||
uint balance;
|
||||
}
|
||||
|
||||
mapping (address => Holder) public Acc;
|
||||
|
||||
Log LogFile;
|
||||
|
||||
uint public MinSum = 1 ether;
|
||||
|
||||
function MY_BANK(address log) public{
|
||||
LogFile = Log(log);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
contract Log
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
address Sender;
|
||||
string Data;
|
||||
uint Val;
|
||||
uint Time;
|
||||
}
|
||||
|
||||
Message[] public History;
|
||||
|
||||
Message LastMsg;
|
||||
|
||||
function AddMessage(address _adr,uint _val,string _data)
|
||||
public
|
||||
{
|
||||
LastMsg.Sender = _adr;
|
||||
LastMsg.Time = now;
|
||||
LastMsg.Val = _val;
|
||||
LastMsg.Data = _data;
|
||||
History.push(LastMsg);
|
||||
}
|
||||
}
|
||||
26
dataset/reentrancy/README.md
Executable file
26
dataset/reentrancy/README.md
Executable file
@@ -0,0 +1,26 @@
|
||||
# Reentrancy
|
||||
Also known as or related to race to empty, recursive call vulnerability, call to the unknown.
|
||||
|
||||
The Reentrancy attack, probably the most famous Ethereum vulnerability,surprised everyone when discovered for the first time. It was first unveiled during a multimillion dollar heist which led to a hard fork of Ethereum. Reentrancy occurs when external contract calls are allowed to make new calls to the calling contract before the initial execution is complete. For a function, this means that the contract state may change in the middle of its execution as a result of a call to an untrusted contract or the use of a low level function with an external address.
|
||||
|
||||
Loss: estimated at 3.5M ETH (~50M USD at the time)
|
||||
|
||||
## Attack Scenario
|
||||
A smart contract tracks the balance of a number of external addresses and allows users to retrieve funds with its public withdraw() function.
|
||||
A malicious smart contract uses the withdraw() function to retrieve its entire balance.
|
||||
The victim contract executes the call.value(amount)() low level function to send the ether to the malicious contract before updating the balance of the malicious contract.
|
||||
The malicious contract has a payable fallback() function that accepts the funds and then calls back into the victim contract's withdraw() function.
|
||||
This second execution triggers a transfer of funds: remember, the balance of the malicious contract still hasn't been updated from the first withdrawal. As a result, the malicious contract successfully withdraws its entire balance a second time.
|
||||
|
||||
## Examples
|
||||
The following function contains a function vulnerable to a reentrancy attack. When the low level call() function sends ether to the msg.sender address, it becomes vulnerable; if the address is a smart contract, the payment will trigger its fallback function with what's left of the transaction gas:
|
||||
```
|
||||
function withdraw(uint _amount) {
|
||||
require(balances[msg.sender] >= _amount);
|
||||
msg.sender.call.value(_amount)();
|
||||
balances[msg.sender] -= _amount;
|
||||
}
|
||||
````
|
||||
|
||||
## References
|
||||
Taken from [DASP TOP10](https://dasp.co/)
|
||||
24
dataset/reentrancy/etherbank.sol
Normal file
24
dataset/reentrancy/etherbank.sol
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* @source: https://github.com/seresistvanandras/EthBench/blob/master/Benchmark/Simple/reentrant.sol
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 21
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.0;
|
||||
contract EtherBank{
|
||||
mapping (address => uint) userBalances;
|
||||
function getBalance(address user) constant returns(uint) {
|
||||
return userBalances[user];
|
||||
}
|
||||
|
||||
function addToBalance() {
|
||||
userBalances[msg.sender] += msg.value;
|
||||
}
|
||||
|
||||
function withdrawBalance() {
|
||||
uint amountToWithdraw = userBalances[msg.sender];
|
||||
// <yes> <report> REENTRANCY
|
||||
if (!(msg.sender.call.value(amountToWithdraw)())) { throw; }
|
||||
userBalances[msg.sender] = 0;
|
||||
}
|
||||
}
|
||||
31
dataset/reentrancy/etherstore.sol
Normal file
31
dataset/reentrancy/etherstore.sol
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* @source: https://github.com/sigp/solidity-security-blog
|
||||
* @author: Suhabe Bugrara
|
||||
* @vulnerable_at_lines: 27
|
||||
*/
|
||||
|
||||
//added pragma version
|
||||
pragma solidity ^0.4.0;
|
||||
|
||||
contract EtherStore {
|
||||
|
||||
uint256 public withdrawalLimit = 1 ether;
|
||||
mapping(address => uint256) public lastWithdrawTime;
|
||||
mapping(address => uint256) public balances;
|
||||
|
||||
function depositFunds() public payable {
|
||||
balances[msg.sender] += msg.value;
|
||||
}
|
||||
|
||||
function withdrawFunds (uint256 _weiToWithdraw) public {
|
||||
require(balances[msg.sender] >= _weiToWithdraw);
|
||||
// limit the withdrawal
|
||||
require(_weiToWithdraw <= withdrawalLimit);
|
||||
// limit the time allowed to withdraw
|
||||
require(now >= lastWithdrawTime[msg.sender] + 1 weeks);
|
||||
// <yes> <report> REENTRANCY
|
||||
require(msg.sender.call.value(_weiToWithdraw)());
|
||||
balances[msg.sender] -= _weiToWithdraw;
|
||||
lastWithdrawTime[msg.sender] = now;
|
||||
}
|
||||
}
|
||||
49
dataset/reentrancy/modifier_reentrancy.sol
Normal file
49
dataset/reentrancy/modifier_reentrancy.sol
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* @source: https://github.com/SmartContractSecurity/SWC-registry/blob/master/test_cases/reentracy/modifier_reentrancy.sol
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 15
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.24;
|
||||
|
||||
contract ModifierEntrancy {
|
||||
mapping (address => uint) public tokenBalance;
|
||||
string constant name = "Nu Token";
|
||||
|
||||
//If a contract has a zero balance and supports the token give them some token
|
||||
// <yes> <report> REENTRANCY
|
||||
function airDrop() hasNoBalance supportsToken public{
|
||||
tokenBalance[msg.sender] += 20;
|
||||
}
|
||||
|
||||
//Checks that the contract responds the way we want
|
||||
modifier supportsToken() {
|
||||
require(keccak256(abi.encodePacked("Nu Token")) == Bank(msg.sender).supportsToken());
|
||||
_;
|
||||
}
|
||||
//Checks that the caller has a zero balance
|
||||
modifier hasNoBalance {
|
||||
require(tokenBalance[msg.sender] == 0);
|
||||
_;
|
||||
}
|
||||
}
|
||||
|
||||
contract Bank{
|
||||
function supportsToken() external pure returns(bytes32){
|
||||
return(keccak256(abi.encodePacked("Nu Token")));
|
||||
}
|
||||
}
|
||||
|
||||
contract attack{ //An example of a contract that breaks the contract above.
|
||||
bool hasBeenCalled;
|
||||
function supportsToken() external returns(bytes32){
|
||||
if(!hasBeenCalled){
|
||||
hasBeenCalled = true;
|
||||
ModifierEntrancy(msg.sender).airDrop();
|
||||
}
|
||||
return(keccak256(abi.encodePacked("Nu Token")));
|
||||
}
|
||||
function call(address token) public{
|
||||
ModifierEntrancy(token).airDrop();
|
||||
}
|
||||
}
|
||||
32
dataset/reentrancy/reentrance.sol
Normal file
32
dataset/reentrancy/reentrance.sol
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* @source: https://ethernaut.zeppelin.solutions/level/0xf70706db003e94cfe4b5e27ffd891d5c81b39488
|
||||
* @author: Alejandro Santander
|
||||
* @vulnerable_at_lines: 24
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.18;
|
||||
|
||||
contract Reentrance {
|
||||
|
||||
mapping(address => uint) public balances;
|
||||
|
||||
function donate(address _to) public payable {
|
||||
balances[_to] += msg.value;
|
||||
}
|
||||
|
||||
function balanceOf(address _who) public view returns (uint balance) {
|
||||
return balances[_who];
|
||||
}
|
||||
|
||||
function withdraw(uint _amount) public {
|
||||
if(balances[msg.sender] >= _amount) {
|
||||
// <yes> <report> REENTRANCY
|
||||
if(msg.sender.call.value(_amount)()) {
|
||||
_amount;
|
||||
}
|
||||
balances[msg.sender] -= _amount;
|
||||
}
|
||||
}
|
||||
|
||||
function() public payable {}
|
||||
}
|
||||
31
dataset/reentrancy/reentrancy_bonus.sol
Normal file
31
dataset/reentrancy/reentrancy_bonus.sol
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* @source: https://consensys.github.io/smart-contract-best-practices/known_attacks/
|
||||
* @author: consensys
|
||||
* @vulnerable_at_lines: 28
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.0;
|
||||
|
||||
contract Reentrancy_bonus{
|
||||
|
||||
// INSECURE
|
||||
mapping (address => uint) private userBalances;
|
||||
mapping (address => bool) private claimedBonus;
|
||||
mapping (address => uint) private rewardsForA;
|
||||
|
||||
function withdrawReward(address recipient) public {
|
||||
uint amountToWithdraw = rewardsForA[recipient];
|
||||
rewardsForA[recipient] = 0;
|
||||
(bool success, ) = recipient.call.value(amountToWithdraw)("");
|
||||
require(success);
|
||||
}
|
||||
|
||||
function getFirstWithdrawalBonus(address recipient) public {
|
||||
require(!claimedBonus[recipient]); // Each recipient should only be able to claim the bonus once
|
||||
|
||||
rewardsForA[recipient] += 100;
|
||||
// <yes> <report> REENTRANCY
|
||||
withdrawReward(recipient); // At this point, the caller will be able to execute getFirstWithdrawalBonus again.
|
||||
claimedBonus[recipient] = true;
|
||||
}
|
||||
}
|
||||
28
dataset/reentrancy/reentrancy_cross_function.sol
Normal file
28
dataset/reentrancy/reentrancy_cross_function.sol
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @source: https://consensys.github.io/smart-contract-best-practices/known_attacks/
|
||||
* @author: consensys
|
||||
* @vulnerable_at_lines: 24
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.0;
|
||||
|
||||
contract Reentrancy_cross_function {
|
||||
|
||||
// INSECURE
|
||||
mapping (address => uint) private userBalances;
|
||||
|
||||
function transfer(address to, uint amount) {
|
||||
if (userBalances[msg.sender] >= amount) {
|
||||
userBalances[to] += amount;
|
||||
userBalances[msg.sender] -= amount;
|
||||
}
|
||||
}
|
||||
|
||||
function withdrawBalance() public {
|
||||
uint amountToWithdraw = userBalances[msg.sender];
|
||||
// <yes> <report> REENTRANCY
|
||||
(bool success, ) = msg.sender.call.value(amountToWithdraw)(""); // At this point, the caller's code is executed, and can call transfer()
|
||||
require(success);
|
||||
userBalances[msg.sender] = 0;
|
||||
}
|
||||
}
|
||||
28
dataset/reentrancy/reentrancy_dao.sol
Normal file
28
dataset/reentrancy/reentrancy_dao.sol
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* @source: https://github.com/ConsenSys/evm-analyzer-benchmark-suite
|
||||
* @author: Suhabe Bugrara
|
||||
* @vulnerable_at_lines: 18
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.19;
|
||||
|
||||
contract ReentrancyDAO {
|
||||
mapping (address => uint) credit;
|
||||
uint balance;
|
||||
|
||||
function withdrawAll() public {
|
||||
uint oCredit = credit[msg.sender];
|
||||
if (oCredit > 0) {
|
||||
balance -= oCredit;
|
||||
// <yes> <report> REENTRANCY
|
||||
bool callResult = msg.sender.call.value(oCredit)();
|
||||
require (callResult);
|
||||
credit[msg.sender] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function deposit() public payable {
|
||||
credit[msg.sender] += msg.value;
|
||||
balance += msg.value;
|
||||
}
|
||||
}
|
||||
21
dataset/reentrancy/reentrancy_insecure.sol
Normal file
21
dataset/reentrancy/reentrancy_insecure.sol
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* @source: https://consensys.github.io/smart-contract-best-practices/known_attacks/
|
||||
* @author: consensys
|
||||
* @vulnerable_at_lines: 17
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.0;
|
||||
|
||||
contract Reentrancy_insecure {
|
||||
|
||||
// INSECURE
|
||||
mapping (address => uint) private userBalances;
|
||||
|
||||
function withdrawBalance() public {
|
||||
uint amountToWithdraw = userBalances[msg.sender];
|
||||
// <yes> <report> REENTRANCY
|
||||
(bool success, ) = msg.sender.call.value(amountToWithdraw)(""); // At this point, the caller's code is executed, and can call withdrawBalance again
|
||||
require(success);
|
||||
userBalances[msg.sender] = 0;
|
||||
}
|
||||
}
|
||||
29
dataset/reentrancy/reentrancy_simple.sol
Normal file
29
dataset/reentrancy/reentrancy_simple.sol
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* @source: https://github.com/trailofbits/not-so-smart-contracts/blob/master/reentrancy/Reentrancy.sol
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 24
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.15;
|
||||
|
||||
contract Reentrance {
|
||||
mapping (address => uint) userBalance;
|
||||
|
||||
function getBalance(address u) constant returns(uint){
|
||||
return userBalance[u];
|
||||
}
|
||||
|
||||
function addToBalance() payable{
|
||||
userBalance[msg.sender] += msg.value;
|
||||
}
|
||||
|
||||
function withdrawBalance(){
|
||||
// send userBalance[msg.sender] ethers to msg.sender
|
||||
// if mgs.sender is a contract, it will call its fallback function
|
||||
// <yes> <report> REENTRANCY
|
||||
if( ! (msg.sender.call.value(userBalance[msg.sender])() ) ){
|
||||
throw;
|
||||
}
|
||||
userBalance[msg.sender] = 0;
|
||||
}
|
||||
}
|
||||
27
dataset/reentrancy/simple_dao.sol
Normal file
27
dataset/reentrancy/simple_dao.sol
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* @source: http://blockchain.unica.it/projects/ethereum-survey/attacks.html#simpledao
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 19
|
||||
*/
|
||||
|
||||
pragma solidity ^0.4.2;
|
||||
|
||||
contract SimpleDAO {
|
||||
mapping (address => uint) public credit;
|
||||
|
||||
function donate(address to) payable {
|
||||
credit[to] += msg.value;
|
||||
}
|
||||
|
||||
function withdraw(uint amount) {
|
||||
if (credit[msg.sender]>= amount) {
|
||||
// <yes> <report> REENTRANCY
|
||||
bool res = msg.sender.call.value(amount)();
|
||||
credit[msg.sender]-=amount;
|
||||
}
|
||||
}
|
||||
|
||||
function queryCredit(address to) returns (uint){
|
||||
return credit[to];
|
||||
}
|
||||
}
|
||||
896
dataset/reentrancy/spank_chain_payment.sol
Normal file
896
dataset/reentrancy/spank_chain_payment.sol
Normal file
@@ -0,0 +1,896 @@
|
||||
/*
|
||||
* @source: https://github.com/trailofbits/not-so-smart-contracts/blob/master/reentrancy/SpankChain_source_code/SpankChain_Payment.sol
|
||||
* @author: -
|
||||
* @vulnerable_at_lines: 426,430
|
||||
*/
|
||||
|
||||
// https://etherscan.io/address/0xf91546835f756da0c10cfa0cda95b15577b84aa7#code
|
||||
|
||||
pragma solidity ^0.4.23;
|
||||
// produced by the Solididy File Flattener (c) David Appleton 2018
|
||||
// contact : dave@akomba.com
|
||||
// released under Apache 2.0 licence
|
||||
contract Token {
|
||||
/* This is a slight change to the ERC20 base standard.
|
||||
function totalSupply() constant returns (uint256 supply);
|
||||
is replaced with:
|
||||
uint256 public totalSupply;
|
||||
This automatically creates a getter function for the totalSupply.
|
||||
This is moved to the base contract since public getter functions are not
|
||||
currently recognised as an implementation of the matching abstract
|
||||
function by the compiler.
|
||||
*/
|
||||
/// total amount of tokens
|
||||
uint256 public totalSupply;
|
||||
|
||||
/// @param _owner The address from which the balance will be retrieved
|
||||
/// @return The balance
|
||||
function balanceOf(address _owner) public constant returns (uint256 balance);
|
||||
|
||||
/// @notice send `_value` token to `_to` from `msg.sender`
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return Whether the transfer was successful or not
|
||||
function transfer(address _to, uint256 _value) public returns (bool success);
|
||||
|
||||
/// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from`
|
||||
/// @param _from The address of the sender
|
||||
/// @param _to The address of the recipient
|
||||
/// @param _value The amount of token to be transferred
|
||||
/// @return Whether the transfer was successful or not
|
||||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
|
||||
|
||||
/// @notice `msg.sender` approves `_spender` to spend `_value` tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @param _value The amount of tokens to be approved for transfer
|
||||
/// @return Whether the approval was successful or not
|
||||
function approve(address _spender, uint256 _value) public returns (bool success);
|
||||
|
||||
/// @param _owner The address of the account owning tokens
|
||||
/// @param _spender The address of the account able to transfer the tokens
|
||||
/// @return Amount of remaining tokens allowed to spent
|
||||
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);
|
||||
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
|
||||
}
|
||||
|
||||
library ECTools {
|
||||
|
||||
// @dev Recovers the address which has signed a message
|
||||
// @thanks https://gist.github.com/axic/5b33912c6f61ae6fd96d6c4a47afde6d
|
||||
function recoverSigner(bytes32 _hashedMsg, string _sig) public pure returns (address) {
|
||||
require(_hashedMsg != 0x00);
|
||||
|
||||
// need this for test RPC
|
||||
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
|
||||
bytes32 prefixedHash = keccak256(abi.encodePacked(prefix, _hashedMsg));
|
||||
|
||||
if (bytes(_sig).length != 132) {
|
||||
return 0x0;
|
||||
}
|
||||
bytes32 r;
|
||||
bytes32 s;
|
||||
uint8 v;
|
||||
bytes memory sig = hexstrToBytes(substring(_sig, 2, 132));
|
||||
assembly {
|
||||
r := mload(add(sig, 32))
|
||||
s := mload(add(sig, 64))
|
||||
v := byte(0, mload(add(sig, 96)))
|
||||
}
|
||||
if (v < 27) {
|
||||
v += 27;
|
||||
}
|
||||
if (v < 27 || v > 28) {
|
||||
return 0x0;
|
||||
}
|
||||
return ecrecover(prefixedHash, v, r, s);
|
||||
}
|
||||
|
||||
// @dev Verifies if the message is signed by an address
|
||||
function isSignedBy(bytes32 _hashedMsg, string _sig, address _addr) public pure returns (bool) {
|
||||
require(_addr != 0x0);
|
||||
|
||||
return _addr == recoverSigner(_hashedMsg, _sig);
|
||||
}
|
||||
|
||||
// @dev Converts an hexstring to bytes
|
||||
function hexstrToBytes(string _hexstr) public pure returns (bytes) {
|
||||
uint len = bytes(_hexstr).length;
|
||||
require(len % 2 == 0);
|
||||
|
||||
bytes memory bstr = bytes(new string(len / 2));
|
||||
uint k = 0;
|
||||
string memory s;
|
||||
string memory r;
|
||||
for (uint i = 0; i < len; i += 2) {
|
||||
s = substring(_hexstr, i, i + 1);
|
||||
r = substring(_hexstr, i + 1, i + 2);
|
||||
uint p = parseInt16Char(s) * 16 + parseInt16Char(r);
|
||||
bstr[k++] = uintToBytes32(p)[31];
|
||||
}
|
||||
return bstr;
|
||||
}
|
||||
|
||||
// @dev Parses a hexchar, like 'a', and returns its hex value, in this case 10
|
||||
function parseInt16Char(string _char) public pure returns (uint) {
|
||||
bytes memory bresult = bytes(_char);
|
||||
// bool decimals = false;
|
||||
if ((bresult[0] >= 48) && (bresult[0] <= 57)) {
|
||||
return uint(bresult[0]) - 48;
|
||||
} else if ((bresult[0] >= 65) && (bresult[0] <= 70)) {
|
||||
return uint(bresult[0]) - 55;
|
||||
} else if ((bresult[0] >= 97) && (bresult[0] <= 102)) {
|
||||
return uint(bresult[0]) - 87;
|
||||
} else {
|
||||
revert();
|
||||
}
|
||||
}
|
||||
|
||||
// @dev Converts a uint to a bytes32
|
||||
// @thanks https://ethereum.stackexchange.com/questions/4170/how-to-convert-a-uint-to-bytes-in-solidity
|
||||
function uintToBytes32(uint _uint) public pure returns (bytes b) {
|
||||
b = new bytes(32);
|
||||
assembly {mstore(add(b, 32), _uint)}
|
||||
}
|
||||
|
||||
// @dev Hashes the signed message
|
||||
// @ref https://github.com/ethereum/go-ethereum/issues/3731#issuecomment-293866868
|
||||
function toEthereumSignedMessage(string _msg) public pure returns (bytes32) {
|
||||
uint len = bytes(_msg).length;
|
||||
require(len > 0);
|
||||
bytes memory prefix = "\x19Ethereum Signed Message:\n";
|
||||
return keccak256(abi.encodePacked(prefix, uintToString(len), _msg));
|
||||
}
|
||||
|
||||
// @dev Converts a uint in a string
|
||||
function uintToString(uint _uint) public pure returns (string str) {
|
||||
uint len = 0;
|
||||
uint m = _uint + 0;
|
||||
while (m != 0) {
|
||||
len++;
|
||||
m /= 10;
|
||||
}
|
||||
bytes memory b = new bytes(len);
|
||||
uint i = len - 1;
|
||||
while (_uint != 0) {
|
||||
uint remainder = _uint % 10;
|
||||
_uint = _uint / 10;
|
||||
b[i--] = byte(48 + remainder);
|
||||
}
|
||||
str = string(b);
|
||||
}
|
||||
|
||||
|
||||
// @dev extract a substring
|
||||
// @thanks https://ethereum.stackexchange.com/questions/31457/substring-in-solidity
|
||||
function substring(string _str, uint _startIndex, uint _endIndex) public pure returns (string) {
|
||||
bytes memory strBytes = bytes(_str);
|
||||
require(_startIndex <= _endIndex);
|
||||
require(_startIndex >= 0);
|
||||
require(_endIndex <= strBytes.length);
|
||||
|
||||
bytes memory result = new bytes(_endIndex - _startIndex);
|
||||
for (uint i = _startIndex; i < _endIndex; i++) {
|
||||
result[i - _startIndex] = strBytes[i];
|
||||
}
|
||||
return string(result);
|
||||
}
|
||||
}
|
||||
contract StandardToken is Token {
|
||||
|
||||
function transfer(address _to, uint256 _value) public returns (bool success) {
|
||||
//Default assumes totalSupply can't be over max (2^256 - 1).
|
||||
//If your token leaves out totalSupply and can issue more tokens as time goes on, you need to check if it doesn't wrap.
|
||||
//Replace the if with this one instead.
|
||||
//require(balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]);
|
||||
require(balances[msg.sender] >= _value);
|
||||
balances[msg.sender] -= _value;
|
||||
balances[_to] += _value;
|
||||
emit Transfer(msg.sender, _to, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
|
||||
//same as above. Replace this line with the following if you want to protect against wrapping uints.
|
||||
//require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]);
|
||||
require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value);
|
||||
balances[_to] += _value;
|
||||
balances[_from] -= _value;
|
||||
allowed[_from][msg.sender] -= _value;
|
||||
emit Transfer(_from, _to, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function balanceOf(address _owner) public constant returns (uint256 balance) {
|
||||
return balances[_owner];
|
||||
}
|
||||
|
||||
function approve(address _spender, uint256 _value) public returns (bool success) {
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
emit Approval(msg.sender, _spender, _value);
|
||||
return true;
|
||||
}
|
||||
|
||||
function allowance(address _owner, address _spender) public constant returns (uint256 remaining) {
|
||||
return allowed[_owner][_spender];
|
||||
}
|
||||
|
||||
mapping (address => uint256) balances;
|
||||
mapping (address => mapping (address => uint256)) allowed;
|
||||
}
|
||||
|
||||
contract HumanStandardToken is StandardToken {
|
||||
|
||||
/* Public variables of the token */
|
||||
|
||||
/*
|
||||
NOTE:
|
||||
The following variables are OPTIONAL vanities. One does not have to include them.
|
||||
They allow one to customise the token contract & in no way influences the core functionality.
|
||||
Some wallets/interfaces might not even bother to look at this information.
|
||||
*/
|
||||
string public name; //fancy name: eg Simon Bucks
|
||||
uint8 public decimals; //How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.
|
||||
string public symbol; //An identifier: eg SBX
|
||||
string public version = 'H0.1'; //human 0.1 standard. Just an arbitrary versioning scheme.
|
||||
|
||||
constructor(
|
||||
uint256 _initialAmount,
|
||||
string _tokenName,
|
||||
uint8 _decimalUnits,
|
||||
string _tokenSymbol
|
||||
) public {
|
||||
balances[msg.sender] = _initialAmount; // Give the creator all initial tokens
|
||||
totalSupply = _initialAmount; // Update total supply
|
||||
name = _tokenName; // Set the name for display purposes
|
||||
decimals = _decimalUnits; // Amount of decimals for display purposes
|
||||
symbol = _tokenSymbol; // Set the symbol for display purposes
|
||||
}
|
||||
|
||||
/* Approves and then calls the receiving contract */
|
||||
function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) {
|
||||
allowed[msg.sender][_spender] = _value;
|
||||
emit Approval(msg.sender, _spender, _value);
|
||||
|
||||
//call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
|
||||
//receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
|
||||
//it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.
|
||||
require(_spender.call(bytes4(bytes32(keccak256("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
contract LedgerChannel {
|
||||
|
||||
string public constant NAME = "Ledger Channel";
|
||||
string public constant VERSION = "0.0.1";
|
||||
|
||||
uint256 public numChannels = 0;
|
||||
|
||||
event DidLCOpen (
|
||||
bytes32 indexed channelId,
|
||||
address indexed partyA,
|
||||
address indexed partyI,
|
||||
uint256 ethBalanceA,
|
||||
address token,
|
||||
uint256 tokenBalanceA,
|
||||
uint256 LCopenTimeout
|
||||
);
|
||||
|
||||
event DidLCJoin (
|
||||
bytes32 indexed channelId,
|
||||
uint256 ethBalanceI,
|
||||
uint256 tokenBalanceI
|
||||
);
|
||||
|
||||
event DidLCDeposit (
|
||||
bytes32 indexed channelId,
|
||||
address indexed recipient,
|
||||
uint256 deposit,
|
||||
bool isToken
|
||||
);
|
||||
|
||||
event DidLCUpdateState (
|
||||
bytes32 indexed channelId,
|
||||
uint256 sequence,
|
||||
uint256 numOpenVc,
|
||||
uint256 ethBalanceA,
|
||||
uint256 tokenBalanceA,
|
||||
uint256 ethBalanceI,
|
||||
uint256 tokenBalanceI,
|
||||
bytes32 vcRoot,
|
||||
uint256 updateLCtimeout
|
||||
);
|
||||
|
||||
event DidLCClose (
|
||||
bytes32 indexed channelId,
|
||||
uint256 sequence,
|
||||
uint256 ethBalanceA,
|
||||
uint256 tokenBalanceA,
|
||||
uint256 ethBalanceI,
|
||||
uint256 tokenBalanceI
|
||||
);
|
||||
|
||||
event DidVCInit (
|
||||
bytes32 indexed lcId,
|
||||
bytes32 indexed vcId,
|
||||
bytes proof,
|
||||
uint256 sequence,
|
||||
address partyA,
|
||||
address partyB,
|
||||
uint256 balanceA,
|
||||
uint256 balanceB
|
||||
);
|
||||
|
||||
event DidVCSettle (
|
||||
bytes32 indexed lcId,
|
||||
bytes32 indexed vcId,
|
||||
uint256 updateSeq,
|
||||
uint256 updateBalA,
|
||||
uint256 updateBalB,
|
||||
address challenger,
|
||||
uint256 updateVCtimeout
|
||||
);
|
||||
|
||||
event DidVCClose(
|
||||
bytes32 indexed lcId,
|
||||
bytes32 indexed vcId,
|
||||
uint256 balanceA,
|
||||
uint256 balanceB
|
||||
);
|
||||
|
||||
struct Channel {
|
||||
//TODO: figure out if it's better just to split arrays by balances/deposits instead of eth/erc20
|
||||
address[2] partyAddresses; // 0: partyA 1: partyI
|
||||
uint256[4] ethBalances; // 0: balanceA 1:balanceI 2:depositedA 3:depositedI
|
||||
uint256[4] erc20Balances; // 0: balanceA 1:balanceI 2:depositedA 3:depositedI
|
||||
uint256[2] initialDeposit; // 0: eth 1: tokens
|
||||
uint256 sequence;
|
||||
uint256 confirmTime;
|
||||
bytes32 VCrootHash;
|
||||
uint256 LCopenTimeout;
|
||||
uint256 updateLCtimeout; // when update LC times out
|
||||
bool isOpen; // true when both parties have joined
|
||||
bool isUpdateLCSettling;
|
||||
uint256 numOpenVC;
|
||||
HumanStandardToken token;
|
||||
}
|
||||
|
||||
// virtual-channel state
|
||||
struct VirtualChannel {
|
||||
bool isClose;
|
||||
bool isInSettlementState;
|
||||
uint256 sequence;
|
||||
address challenger; // Initiator of challenge
|
||||
uint256 updateVCtimeout; // when update VC times out
|
||||
// channel state
|
||||
address partyA; // VC participant A
|
||||
address partyB; // VC participant B
|
||||
address partyI; // LC hub
|
||||
uint256[2] ethBalances;
|
||||
uint256[2] erc20Balances;
|
||||
uint256[2] bond;
|
||||
HumanStandardToken token;
|
||||
}
|
||||
|
||||
mapping(bytes32 => VirtualChannel) public virtualChannels;
|
||||
mapping(bytes32 => Channel) public Channels;
|
||||
|
||||
function createChannel(
|
||||
bytes32 _lcID,
|
||||
address _partyI,
|
||||
uint256 _confirmTime,
|
||||
address _token,
|
||||
uint256[2] _balances // [eth, token]
|
||||
)
|
||||
public
|
||||
payable
|
||||
{
|
||||
require(Channels[_lcID].partyAddresses[0] == address(0), "Channel has already been created.");
|
||||
require(_partyI != 0x0, "No partyI address provided to LC creation");
|
||||
require(_balances[0] >= 0 && _balances[1] >= 0, "Balances cannot be negative");
|
||||
// Set initial ledger channel state
|
||||
// Alice must execute this and we assume the initial state
|
||||
// to be signed from this requirement
|
||||
// Alternative is to check a sig as in joinChannel
|
||||
Channels[_lcID].partyAddresses[0] = msg.sender;
|
||||
Channels[_lcID].partyAddresses[1] = _partyI;
|
||||
|
||||
if(_balances[0] != 0) {
|
||||
require(msg.value == _balances[0], "Eth balance does not match sent value");
|
||||
Channels[_lcID].ethBalances[0] = msg.value;
|
||||
}
|
||||
if(_balances[1] != 0) {
|
||||
Channels[_lcID].token = HumanStandardToken(_token);
|
||||
require(Channels[_lcID].token.transferFrom(msg.sender, this, _balances[1]),"CreateChannel: token transfer failure");
|
||||
Channels[_lcID].erc20Balances[0] = _balances[1];
|
||||
}
|
||||
|
||||
Channels[_lcID].sequence = 0;
|
||||
Channels[_lcID].confirmTime = _confirmTime;
|
||||
// is close flag, lc state sequence, number open vc, vc root hash, partyA...
|
||||
//Channels[_lcID].stateHash = keccak256(uint256(0), uint256(0), uint256(0), bytes32(0x0), bytes32(msg.sender), bytes32(_partyI), balanceA, balanceI);
|
||||
Channels[_lcID].LCopenTimeout = now + _confirmTime;
|
||||
Channels[_lcID].initialDeposit = _balances;
|
||||
|
||||
emit DidLCOpen(_lcID, msg.sender, _partyI, _balances[0], _token, _balances[1], Channels[_lcID].LCopenTimeout);
|
||||
}
|
||||
|
||||
function LCOpenTimeout(bytes32 _lcID) public {
|
||||
require(msg.sender == Channels[_lcID].partyAddresses[0] && Channels[_lcID].isOpen == false);
|
||||
require(now > Channels[_lcID].LCopenTimeout);
|
||||
|
||||
if(Channels[_lcID].initialDeposit[0] != 0) {
|
||||
// <yes> <report> REENTRANCY
|
||||
Channels[_lcID].partyAddresses[0].transfer(Channels[_lcID].ethBalances[0]);
|
||||
}
|
||||
if(Channels[_lcID].initialDeposit[1] != 0) {
|
||||
// <yes> <report> REENTRANCY
|
||||
require(Channels[_lcID].token.transfer(Channels[_lcID].partyAddresses[0], Channels[_lcID].erc20Balances[0]),"CreateChannel: token transfer failure");
|
||||
}
|
||||
|
||||
emit DidLCClose(_lcID, 0, Channels[_lcID].ethBalances[0], Channels[_lcID].erc20Balances[0], 0, 0);
|
||||
|
||||
// only safe to delete since no action was taken on this channel
|
||||
delete Channels[_lcID];
|
||||
}
|
||||
|
||||
function joinChannel(bytes32 _lcID, uint256[2] _balances) public payable {
|
||||
// require the channel is not open yet
|
||||
require(Channels[_lcID].isOpen == false);
|
||||
require(msg.sender == Channels[_lcID].partyAddresses[1]);
|
||||
|
||||
if(_balances[0] != 0) {
|
||||
require(msg.value == _balances[0], "state balance does not match sent value");
|
||||
Channels[_lcID].ethBalances[1] = msg.value;
|
||||
}
|
||||
if(_balances[1] != 0) {
|
||||
require(Channels[_lcID].token.transferFrom(msg.sender, this, _balances[1]),"joinChannel: token transfer failure");
|
||||
Channels[_lcID].erc20Balances[1] = _balances[1];
|
||||
}
|
||||
|
||||
Channels[_lcID].initialDeposit[0]+=_balances[0];
|
||||
Channels[_lcID].initialDeposit[1]+=_balances[1];
|
||||
// no longer allow joining functions to be called
|
||||
Channels[_lcID].isOpen = true;
|
||||
numChannels++;
|
||||
|
||||
emit DidLCJoin(_lcID, _balances[0], _balances[1]);
|
||||
}
|
||||
|
||||
|
||||
// additive updates of monetary state
|
||||
// TODO check this for attack vectors
|
||||
function deposit(bytes32 _lcID, address recipient, uint256 _balance, bool isToken) public payable {
|
||||
require(Channels[_lcID].isOpen == true, "Tried adding funds to a closed channel");
|
||||
require(recipient == Channels[_lcID].partyAddresses[0] || recipient == Channels[_lcID].partyAddresses[1]);
|
||||
|
||||
//if(Channels[_lcID].token)
|
||||
|
||||
if (Channels[_lcID].partyAddresses[0] == recipient) {
|
||||
if(isToken) {
|
||||
require(Channels[_lcID].token.transferFrom(msg.sender, this, _balance),"deposit: token transfer failure");
|
||||
Channels[_lcID].erc20Balances[2] += _balance;
|
||||
} else {
|
||||
require(msg.value == _balance, "state balance does not match sent value");
|
||||
Channels[_lcID].ethBalances[2] += msg.value;
|
||||
}
|
||||
}
|
||||
|
||||
if (Channels[_lcID].partyAddresses[1] == recipient) {
|
||||
if(isToken) {
|
||||
require(Channels[_lcID].token.transferFrom(msg.sender, this, _balance),"deposit: token transfer failure");
|
||||
Channels[_lcID].erc20Balances[3] += _balance;
|
||||
} else {
|
||||
require(msg.value == _balance, "state balance does not match sent value");
|
||||
Channels[_lcID].ethBalances[3] += msg.value;
|
||||
}
|
||||
}
|
||||
|
||||
emit DidLCDeposit(_lcID, recipient, _balance, isToken);
|
||||
}
|
||||
|
||||
// TODO: Check there are no open virtual channels, the client should have cought this before signing a close LC state update
|
||||
function consensusCloseChannel(
|
||||
bytes32 _lcID,
|
||||
uint256 _sequence,
|
||||
uint256[4] _balances, // 0: ethBalanceA 1:ethBalanceI 2:tokenBalanceA 3:tokenBalanceI
|
||||
string _sigA,
|
||||
string _sigI
|
||||
)
|
||||
public
|
||||
{
|
||||
// assume num open vc is 0 and root hash is 0x0
|
||||
//require(Channels[_lcID].sequence < _sequence);
|
||||
require(Channels[_lcID].isOpen == true);
|
||||
uint256 totalEthDeposit = Channels[_lcID].initialDeposit[0] + Channels[_lcID].ethBalances[2] + Channels[_lcID].ethBalances[3];
|
||||
uint256 totalTokenDeposit = Channels[_lcID].initialDeposit[1] + Channels[_lcID].erc20Balances[2] + Channels[_lcID].erc20Balances[3];
|
||||
require(totalEthDeposit == _balances[0] + _balances[1]);
|
||||
require(totalTokenDeposit == _balances[2] + _balances[3]);
|
||||
|
||||
bytes32 _state = keccak256(
|
||||
abi.encodePacked(
|
||||
_lcID,
|
||||
true,
|
||||
_sequence,
|
||||
uint256(0),
|
||||
bytes32(0x0),
|
||||
Channels[_lcID].partyAddresses[0],
|
||||
Channels[_lcID].partyAddresses[1],
|
||||
_balances[0],
|
||||
_balances[1],
|
||||
_balances[2],
|
||||
_balances[3]
|
||||
)
|
||||
);
|
||||
|
||||
require(Channels[_lcID].partyAddresses[0] == ECTools.recoverSigner(_state, _sigA));
|
||||
require(Channels[_lcID].partyAddresses[1] == ECTools.recoverSigner(_state, _sigI));
|
||||
|
||||
Channels[_lcID].isOpen = false;
|
||||
|
||||
if(_balances[0] != 0 || _balances[1] != 0) {
|
||||
Channels[_lcID].partyAddresses[0].transfer(_balances[0]);
|
||||
Channels[_lcID].partyAddresses[1].transfer(_balances[1]);
|
||||
}
|
||||
|
||||
if(_balances[2] != 0 || _balances[3] != 0) {
|
||||
require(Channels[_lcID].token.transfer(Channels[_lcID].partyAddresses[0], _balances[2]),"happyCloseChannel: token transfer failure");
|
||||
require(Channels[_lcID].token.transfer(Channels[_lcID].partyAddresses[1], _balances[3]),"happyCloseChannel: token transfer failure");
|
||||
}
|
||||
|
||||
numChannels--;
|
||||
|
||||
emit DidLCClose(_lcID, _sequence, _balances[0], _balances[1], _balances[2], _balances[3]);
|
||||
}
|
||||
|
||||
// Byzantine functions
|
||||
|
||||
function updateLCstate(
|
||||
bytes32 _lcID,
|
||||
uint256[6] updateParams, // [sequence, numOpenVc, ethbalanceA, ethbalanceI, tokenbalanceA, tokenbalanceI]
|
||||
bytes32 _VCroot,
|
||||
string _sigA,
|
||||
string _sigI
|
||||
)
|
||||
public
|
||||
{
|
||||
Channel storage channel = Channels[_lcID];
|
||||
require(channel.isOpen);
|
||||
require(channel.sequence < updateParams[0]); // do same as vc sequence check
|
||||
require(channel.ethBalances[0] + channel.ethBalances[1] >= updateParams[2] + updateParams[3]);
|
||||
require(channel.erc20Balances[0] + channel.erc20Balances[1] >= updateParams[4] + updateParams[5]);
|
||||
|
||||
if(channel.isUpdateLCSettling == true) {
|
||||
require(channel.updateLCtimeout > now);
|
||||
}
|
||||
|
||||
bytes32 _state = keccak256(
|
||||
abi.encodePacked(
|
||||
_lcID,
|
||||
false,
|
||||
updateParams[0],
|
||||
updateParams[1],
|
||||
_VCroot,
|
||||
channel.partyAddresses[0],
|
||||
channel.partyAddresses[1],
|
||||
updateParams[2],
|
||||
updateParams[3],
|
||||
updateParams[4],
|
||||
updateParams[5]
|
||||
)
|
||||
);
|
||||
|
||||
require(channel.partyAddresses[0] == ECTools.recoverSigner(_state, _sigA));
|
||||
require(channel.partyAddresses[1] == ECTools.recoverSigner(_state, _sigI));
|
||||
|
||||
// update LC state
|
||||
channel.sequence = updateParams[0];
|
||||
channel.numOpenVC = updateParams[1];
|
||||
channel.ethBalances[0] = updateParams[2];
|
||||
channel.ethBalances[1] = updateParams[3];
|
||||
channel.erc20Balances[0] = updateParams[4];
|
||||
channel.erc20Balances[1] = updateParams[5];
|
||||
channel.VCrootHash = _VCroot;
|
||||
channel.isUpdateLCSettling = true;
|
||||
channel.updateLCtimeout = now + channel.confirmTime;
|
||||
|
||||
// make settlement flag
|
||||
|
||||
emit DidLCUpdateState (
|
||||
_lcID,
|
||||
updateParams[0],
|
||||
updateParams[1],
|
||||
updateParams[2],
|
||||
updateParams[3],
|
||||
updateParams[4],
|
||||
updateParams[5],
|
||||
_VCroot,
|
||||
channel.updateLCtimeout
|
||||
);
|
||||
}
|
||||
|
||||
// supply initial state of VC to "prime" the force push game
|
||||
function initVCstate(
|
||||
bytes32 _lcID,
|
||||
bytes32 _vcID,
|
||||
bytes _proof,
|
||||
address _partyA,
|
||||
address _partyB,
|
||||
uint256[2] _bond,
|
||||
uint256[4] _balances, // 0: ethBalanceA 1:ethBalanceI 2:tokenBalanceA 3:tokenBalanceI
|
||||
string sigA
|
||||
)
|
||||
public
|
||||
{
|
||||
require(Channels[_lcID].isOpen, "LC is closed.");
|
||||
// sub-channel must be open
|
||||
require(!virtualChannels[_vcID].isClose, "VC is closed.");
|
||||
// Check time has passed on updateLCtimeout and has not passed the time to store a vc state
|
||||
require(Channels[_lcID].updateLCtimeout < now, "LC timeout not over.");
|
||||
// prevent rentry of initializing vc state
|
||||
require(virtualChannels[_vcID].updateVCtimeout == 0);
|
||||
// partyB is now Ingrid
|
||||
bytes32 _initState = keccak256(
|
||||
abi.encodePacked(_vcID, uint256(0), _partyA, _partyB, _bond[0], _bond[1], _balances[0], _balances[1], _balances[2], _balances[3])
|
||||
);
|
||||
|
||||
// Make sure Alice has signed initial vc state (A/B in oldState)
|
||||
require(_partyA == ECTools.recoverSigner(_initState, sigA));
|
||||
|
||||
// Check the oldState is in the root hash
|
||||
require(_isContained(_initState, _proof, Channels[_lcID].VCrootHash) == true);
|
||||
|
||||
virtualChannels[_vcID].partyA = _partyA; // VC participant A
|
||||
virtualChannels[_vcID].partyB = _partyB; // VC participant B
|
||||
virtualChannels[_vcID].sequence = uint256(0);
|
||||
virtualChannels[_vcID].ethBalances[0] = _balances[0];
|
||||
virtualChannels[_vcID].ethBalances[1] = _balances[1];
|
||||
virtualChannels[_vcID].erc20Balances[0] = _balances[2];
|
||||
virtualChannels[_vcID].erc20Balances[1] = _balances[3];
|
||||
virtualChannels[_vcID].bond = _bond;
|
||||
virtualChannels[_vcID].updateVCtimeout = now + Channels[_lcID].confirmTime;
|
||||
virtualChannels[_vcID].isInSettlementState = true;
|
||||
|
||||
emit DidVCInit(_lcID, _vcID, _proof, uint256(0), _partyA, _partyB, _balances[0], _balances[1]);
|
||||
}
|
||||
|
||||
//TODO: verify state transition since the hub did not agree to this state
|
||||
// make sure the A/B balances are not beyond ingrids bonds
|
||||
// Params: vc init state, vc final balance, vcID
|
||||
function settleVC(
|
||||
bytes32 _lcID,
|
||||
bytes32 _vcID,
|
||||
uint256 updateSeq,
|
||||
address _partyA,
|
||||
address _partyB,
|
||||
uint256[4] updateBal, // [ethupdateBalA, ethupdateBalB, tokenupdateBalA, tokenupdateBalB]
|
||||
string sigA
|
||||
)
|
||||
public
|
||||
{
|
||||
require(Channels[_lcID].isOpen, "LC is closed.");
|
||||
// sub-channel must be open
|
||||
require(!virtualChannels[_vcID].isClose, "VC is closed.");
|
||||
require(virtualChannels[_vcID].sequence < updateSeq, "VC sequence is higher than update sequence.");
|
||||
require(
|
||||
virtualChannels[_vcID].ethBalances[1] < updateBal[1] && virtualChannels[_vcID].erc20Balances[1] < updateBal[3],
|
||||
"State updates may only increase recipient balance."
|
||||
);
|
||||
require(
|
||||
virtualChannels[_vcID].bond[0] == updateBal[0] + updateBal[1] &&
|
||||
virtualChannels[_vcID].bond[1] == updateBal[2] + updateBal[3],
|
||||
"Incorrect balances for bonded amount");
|
||||
// Check time has passed on updateLCtimeout and has not passed the time to store a vc state
|
||||
// virtualChannels[_vcID].updateVCtimeout should be 0 on uninitialized vc state, and this should
|
||||
// fail if initVC() isn't called first
|
||||
// require(Channels[_lcID].updateLCtimeout < now && now < virtualChannels[_vcID].updateVCtimeout);
|
||||
require(Channels[_lcID].updateLCtimeout < now); // for testing!
|
||||
|
||||
bytes32 _updateState = keccak256(
|
||||
abi.encodePacked(
|
||||
_vcID,
|
||||
updateSeq,
|
||||
_partyA,
|
||||
_partyB,
|
||||
virtualChannels[_vcID].bond[0],
|
||||
virtualChannels[_vcID].bond[1],
|
||||
updateBal[0],
|
||||
updateBal[1],
|
||||
updateBal[2],
|
||||
updateBal[3]
|
||||
)
|
||||
);
|
||||
|
||||
// Make sure Alice has signed a higher sequence new state
|
||||
require(virtualChannels[_vcID].partyA == ECTools.recoverSigner(_updateState, sigA));
|
||||
|
||||
// store VC data
|
||||
// we may want to record who is initiating on-chain settles
|
||||
virtualChannels[_vcID].challenger = msg.sender;
|
||||
virtualChannels[_vcID].sequence = updateSeq;
|
||||
|
||||
// channel state
|
||||
virtualChannels[_vcID].ethBalances[0] = updateBal[0];
|
||||
virtualChannels[_vcID].ethBalances[1] = updateBal[1];
|
||||
virtualChannels[_vcID].erc20Balances[0] = updateBal[2];
|
||||
virtualChannels[_vcID].erc20Balances[1] = updateBal[3];
|
||||
|
||||
virtualChannels[_vcID].updateVCtimeout = now + Channels[_lcID].confirmTime;
|
||||
|
||||
emit DidVCSettle(_lcID, _vcID, updateSeq, updateBal[0], updateBal[1], msg.sender, virtualChannels[_vcID].updateVCtimeout);
|
||||
}
|
||||
|
||||
function closeVirtualChannel(bytes32 _lcID, bytes32 _vcID) public {
|
||||
// require(updateLCtimeout > now)
|
||||
require(Channels[_lcID].isOpen, "LC is closed.");
|
||||
require(virtualChannels[_vcID].isInSettlementState, "VC is not in settlement state.");
|
||||
require(virtualChannels[_vcID].updateVCtimeout < now, "Update vc timeout has not elapsed.");
|
||||
require(!virtualChannels[_vcID].isClose, "VC is already closed");
|
||||
// reduce the number of open virtual channels stored on LC
|
||||
Channels[_lcID].numOpenVC--;
|
||||
// close vc flags
|
||||
virtualChannels[_vcID].isClose = true;
|
||||
// re-introduce the balances back into the LC state from the settled VC
|
||||
// decide if this lc is alice or bob in the vc
|
||||
if(virtualChannels[_vcID].partyA == Channels[_lcID].partyAddresses[0]) {
|
||||
Channels[_lcID].ethBalances[0] += virtualChannels[_vcID].ethBalances[0];
|
||||
Channels[_lcID].ethBalances[1] += virtualChannels[_vcID].ethBalances[1];
|
||||
|
||||
Channels[_lcID].erc20Balances[0] += virtualChannels[_vcID].erc20Balances[0];
|
||||
Channels[_lcID].erc20Balances[1] += virtualChannels[_vcID].erc20Balances[1];
|
||||
} else if (virtualChannels[_vcID].partyB == Channels[_lcID].partyAddresses[0]) {
|
||||
Channels[_lcID].ethBalances[0] += virtualChannels[_vcID].ethBalances[1];
|
||||
Channels[_lcID].ethBalances[1] += virtualChannels[_vcID].ethBalances[0];
|
||||
|
||||
Channels[_lcID].erc20Balances[0] += virtualChannels[_vcID].erc20Balances[1];
|
||||
Channels[_lcID].erc20Balances[1] += virtualChannels[_vcID].erc20Balances[0];
|
||||
}
|
||||
|
||||
emit DidVCClose(_lcID, _vcID, virtualChannels[_vcID].erc20Balances[0], virtualChannels[_vcID].erc20Balances[1]);
|
||||
}
|
||||
|
||||
|
||||
// todo: allow ethier lc.end-user to nullify the settled LC state and return to off-chain
|
||||
function byzantineCloseChannel(bytes32 _lcID) public {
|
||||
Channel storage channel = Channels[_lcID];
|
||||
|
||||
// check settlement flag
|
||||
require(channel.isOpen, "Channel is not open");
|
||||
require(channel.isUpdateLCSettling == true);
|
||||
require(channel.numOpenVC == 0);
|
||||
require(channel.updateLCtimeout < now, "LC timeout over.");
|
||||
|
||||
// if off chain state update didnt reblance deposits, just return to deposit owner
|
||||
uint256 totalEthDeposit = channel.initialDeposit[0] + channel.ethBalances[2] + channel.ethBalances[3];
|
||||
uint256 totalTokenDeposit = channel.initialDeposit[1] + channel.erc20Balances[2] + channel.erc20Balances[3];
|
||||
|
||||
uint256 possibleTotalEthBeforeDeposit = channel.ethBalances[0] + channel.ethBalances[1];
|
||||
uint256 possibleTotalTokenBeforeDeposit = channel.erc20Balances[0] + channel.erc20Balances[1];
|
||||
|
||||
if(possibleTotalEthBeforeDeposit < totalEthDeposit) {
|
||||
channel.ethBalances[0]+=channel.ethBalances[2];
|
||||
channel.ethBalances[1]+=channel.ethBalances[3];
|
||||
} else {
|
||||
require(possibleTotalEthBeforeDeposit == totalEthDeposit);
|
||||
}
|
||||
|
||||
if(possibleTotalTokenBeforeDeposit < totalTokenDeposit) {
|
||||
channel.erc20Balances[0]+=channel.erc20Balances[2];
|
||||
channel.erc20Balances[1]+=channel.erc20Balances[3];
|
||||
} else {
|
||||
require(possibleTotalTokenBeforeDeposit == totalTokenDeposit);
|
||||
}
|
||||
|
||||
// reentrancy
|
||||
uint256 ethbalanceA = channel.ethBalances[0];
|
||||
uint256 ethbalanceI = channel.ethBalances[1];
|
||||
uint256 tokenbalanceA = channel.erc20Balances[0];
|
||||
uint256 tokenbalanceI = channel.erc20Balances[1];
|
||||
|
||||
channel.ethBalances[0] = 0;
|
||||
channel.ethBalances[1] = 0;
|
||||
channel.erc20Balances[0] = 0;
|
||||
channel.erc20Balances[1] = 0;
|
||||
|
||||
if(ethbalanceA != 0 || ethbalanceI != 0) {
|
||||
channel.partyAddresses[0].transfer(ethbalanceA);
|
||||
channel.partyAddresses[1].transfer(ethbalanceI);
|
||||
}
|
||||
|
||||
if(tokenbalanceA != 0 || tokenbalanceI != 0) {
|
||||
require(
|
||||
channel.token.transfer(channel.partyAddresses[0], tokenbalanceA),
|
||||
"byzantineCloseChannel: token transfer failure"
|
||||
);
|
||||
require(
|
||||
channel.token.transfer(channel.partyAddresses[1], tokenbalanceI),
|
||||
"byzantineCloseChannel: token transfer failure"
|
||||
);
|
||||
}
|
||||
|
||||
channel.isOpen = false;
|
||||
numChannels--;
|
||||
|
||||
emit DidLCClose(_lcID, channel.sequence, ethbalanceA, ethbalanceI, tokenbalanceA, tokenbalanceI);
|
||||
}
|
||||
|
||||
function _isContained(bytes32 _hash, bytes _proof, bytes32 _root) internal pure returns (bool) {
|
||||
bytes32 cursor = _hash;
|
||||
bytes32 proofElem;
|
||||
|
||||
for (uint256 i = 64; i <= _proof.length; i += 32) {
|
||||
assembly { proofElem := mload(add(_proof, i)) }
|
||||
|
||||
if (cursor < proofElem) {
|
||||
cursor = keccak256(abi.encodePacked(cursor, proofElem));
|
||||
} else {
|
||||
cursor = keccak256(abi.encodePacked(proofElem, cursor));
|
||||
}
|
||||
}
|
||||
|
||||
return cursor == _root;
|
||||
}
|
||||
|
||||
//Struct Getters
|
||||
function getChannel(bytes32 id) public view returns (
|
||||
address[2],
|
||||
uint256[4],
|
||||
uint256[4],
|
||||
uint256[2],
|
||||
uint256,
|
||||
uint256,
|
||||
bytes32,
|
||||
uint256,
|
||||
uint256,
|
||||
bool,
|
||||
bool,
|
||||
uint256
|
||||
) {
|
||||
Channel memory channel = Channels[id];
|
||||
return (
|
||||
channel.partyAddresses,
|
||||
channel.ethBalances,
|
||||
channel.erc20Balances,
|
||||
channel.initialDeposit,
|
||||
channel.sequence,
|
||||
channel.confirmTime,
|
||||
channel.VCrootHash,
|
||||
channel.LCopenTimeout,
|
||||
channel.updateLCtimeout,
|
||||
channel.isOpen,
|
||||
channel.isUpdateLCSettling,
|
||||
channel.numOpenVC
|
||||
);
|
||||
}
|
||||
|
||||
function getVirtualChannel(bytes32 id) public view returns(
|
||||
bool,
|
||||
bool,
|
||||
uint256,
|
||||
address,
|
||||
uint256,
|
||||
address,
|
||||
address,
|
||||
address,
|
||||
uint256[2],
|
||||
uint256[2],
|
||||
uint256[2]
|
||||
) {
|
||||
VirtualChannel memory virtualChannel = virtualChannels[id];
|
||||
return(
|
||||
virtualChannel.isClose,
|
||||
virtualChannel.isInSettlementState,
|
||||
virtualChannel.sequence,
|
||||
virtualChannel.challenger,
|
||||
virtualChannel.updateVCtimeout,
|
||||
virtualChannel.partyA,
|
||||
virtualChannel.partyB,
|
||||
virtualChannel.partyI,
|
||||
virtualChannel.ethBalances,
|
||||
virtualChannel.erc20Balances,
|
||||
virtualChannel.bond
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user