/**
* This smart contract code is Copyright 2017 TokenMarket Ltd. For more information see https://tokenmarket.net
*
* Licensed under the Apache License, version 2.0: https://github.com/TokenMarketNet/ico/blob/master/LICENSE.txt
*/
/**
* This smart contract code is Copyright 2017 TokenMarket Ltd. For more information see https://tokenmarket.net
*
* Licensed under the Apache License, version 2.0: https://github.com/TokenMarketNet/ico/blob/master/LICENSE.txt
*/
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) onlyOwner {
require(newOwner != address(0));
owner = newOwner;
}
}
/*
* Haltable
*
* Abstract contract that allows children to implement an
* emergency stop mechanism. Differs from Pausable by causing a throw when in halt mode.
*
*
* Originally envisioned in FirstBlood ICO contract.
*/
contract Haltable is Ownable {
bool public halted;
modifier stopInEmergency {
if (halted) throw;
_;
}
modifier stopNonOwnersInEmergency {
if (halted && msg.sender != owner) throw;
_;
}
modifier onlyInEmergency {
if (!halted) throw;
_;
}
// called by the owner on emergency, triggers stopped state
function halt() external onlyOwner {
halted = true;
}
// called by the owner on end of emergency, returns to normal state
function unhalt() external onlyOwner onlyInEmergency {
halted = false;
}
}
/**
* Forward Ethereum payments to another wallet and track them with an event.
*
* Allows to identify customers who made Ethereum payment for a central token issuance.
* Furthermore allow making a payment on behalf of another address.
*
* Allow pausing to signal the end of the crowdsale.
*/
contract PaymentForwarder is Haltable {
/** Who will get all ETH in the end */
address public teamMultisig;
/** Total incoming money */
uint public totalTransferred;
/** How many distinct customers we have that have made a payment */
uint public customerCount;
/** Total incoming money per centrally tracked customer id */
mapping(uint128 => uint) public paymentsByCustomer;
/** Total incoming money per benefactor address */
mapping(address => uint) public paymentsByBenefactor;
/** A customer has made a payment. Benefactor is the address where the tokens will be ultimately issued.*/
event PaymentForwarded(address source, uint amount, uint128 customerId, address benefactor);
function PaymentForwarder(address _owner, address _teamMultisig) {
teamMultisig = _teamMultisig;
owner = _owner;
}
function payWithoutChecksum(uint128 customerId, address benefactor) public stopInEmergency payable {
uint weiAmount = msg.value;
PaymentForwarded(msg.sender, weiAmount, customerId, benefactor);
// We trust Ethereum amounts cannot overflow uint256
totalTransferred += weiAmount;
if(paymentsByCustomer[customerId] == 0) {
customerCount++;
}
paymentsByCustomer[customerId] += weiAmount;
// We track benefactor addresses for extra safety;
// In the case of central ETH issuance tracking has problems we can
// construct ETH contributions solely based on blockchain data
paymentsByBenefactor[benefactor] += weiAmount;
// May run out of gas
if(!teamMultisig.send(weiAmount)) throw;
}
/**
* Pay on a behalf of an address.
*
* @param customerId Identifier in the central database, UUID v4
*
*/
function pay(uint128 customerId, address benefactor, bytes1 checksum) public stopInEmergency payable {
// see customerid.py
if (bytes1(sha3(customerId, benefactor)) != checksum) throw;
payWithoutChecksum(customerId, benefactor);
}
/**
* Pay on a behalf of the sender.
*
* @param customerId Identifier in the central database, UUID v4
*
*/
function payForMyselfWithChecksum(uint128 customerId, bytes1 checksum) public payable {
// see customerid.py
if (bytes1(sha3(customerId)) != checksum) throw;
payWithoutChecksum(customerId, msg.sender);
}
/**
* Legacy API signature.
*/
function payForMyself(uint128 customerId) public payable {
payWithoutChecksum(customerId, msg.sender);
}
}
{
"compilationTarget": {
"PaymentForwarder.sol": "PaymentForwarder"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 500
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"customerId","type":"uint128"}],"name":"payForMyself","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"customerId","type":"uint128"},{"name":"benefactor","type":"address"}],"name":"payWithoutChecksum","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"customerId","type":"uint128"},{"name":"checksum","type":"bytes1"}],"name":"payForMyselfWithChecksum","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"halt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"customerCount","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalTransferred","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"halted","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"customerId","type":"uint128"},{"name":"benefactor","type":"address"},{"name":"checksum","type":"bytes1"}],"name":"pay","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[],"name":"unhalt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"teamMultisig","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"paymentsByBenefactor","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint128"}],"name":"paymentsByCustomer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_owner","type":"address"},{"name":"_teamMultisig","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"source","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"customerId","type":"uint128"},{"indexed":false,"name":"benefactor","type":"address"}],"name":"PaymentForwarded","type":"event"}]