133 lines
3.9 KiB
Solidity
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
|
|
}
|
|
}
|
|
|
|
}
|