smartbugs-curated/dataset/unchecked_low_level_calls/0xec329ffc97d75fe03428ae155...

133 lines
3.9 KiB
Solidity

/*
* @source: etherscan.io
* @author: -
* @vulnerable_at_lines: 30
*/
pragma solidity ^0.4.11; /* originally >=0.4.11 */
contract Owned {
function Owned() {
owner = msg.sender;
}
address public owner;
// This contract only defines a modifier and a few useful functions
// The function body is inserted where the special symbol "_" in the
// definition of a modifier appears.
modifier onlyOwner { if (msg.sender == owner) _; }
function changeOwner(address _newOwner) onlyOwner {
owner = _newOwner;
}
// This is a general safty function that allows the owner to do a lot
// of things in the unlikely event that something goes wrong
// _dst is the contract being called making this like a 1/1 multisig
function execute(address _dst, uint _value, bytes _data) onlyOwner {
// <yes> <report> UNCHECKED_LL_CALLS
_dst.call.value(_value)(_data);
}
}
// to get the needed token functions in the contract
contract Token {
function transfer(address, uint) returns(bool);
function balanceOf(address) constant returns (uint);
}
contract TokenSender is Owned {
Token public token; // the token we are working with
uint public totalToDistribute;
uint public next;
struct Transfer {
address addr;
uint amount;
}
Transfer[] public transfers;
function TokenSender(address _token) {
token = Token(_token);
}
// this is a used to save gas
uint constant D160 = 0x0010000000000000000000000000000000000000000;
// This is the function that makes the list of transfers and various
// checks around that list, it is a little tricky, the data input is
// structured with the `amount` and the (receiving) `addr` combined as one
// long number and then this number is deconstructed in this function to
// save gas and reduce the number of `0`'s that are needed to be stored
// on the blockchain
function fill(uint[] data) onlyOwner {
// If the send has started then we just throw
if (next>0) throw;
uint acc;
uint offset = transfers.length;
transfers.length = transfers.length + data.length;
for (uint i = 0; i < data.length; i++ ) {
address addr = address( data[i] & (D160-1) );
uint amount = data[i] / D160;
transfers[offset + i].addr = addr;
transfers[offset + i].amount = amount;
acc += amount;
}
totalToDistribute += acc;
}
// This function actually makes the sends and tracks the amount of gas used
// if it takes more gas than was sent with the transaction then this
// function will need to be called a few times until
function run() onlyOwner {
if (transfers.length == 0) return;
// Keep next in the stack var mNext to save gas
uint mNext = next;
// Set the contract as finalized to avoid reentrance
next = transfers.length;
if ((mNext == 0 ) && ( token.balanceOf(this) != totalToDistribute)) throw;
while ((mNext<transfers.length) && ( gas() > 150000 )) {
uint amount = transfers[mNext].amount;
address addr = transfers[mNext].addr;
if (amount > 0) {
if (!token.transfer(addr, transfers[mNext].amount)) throw;
}
mNext ++;
}
// Set the next to the actual state.
next = mNext;
}
///////////////////////
// Helper functions
///////////////////////
function hasTerminated() constant returns (bool) {
if (transfers.length == 0) return false;
if (next < transfers.length) return false;
return true;
}
function nTransfers() constant returns (uint) {
return transfers.length;
}
function gas() internal constant returns (uint _gas) {
assembly {
_gas:= gas
}
}
}