Created using browser-solidity: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://ethereum.github.io/browser-solidity/#version=soljson-v0.4.20+commit.3155dd80.js&optimize=false&gist=

February 21, 2018 ยท View on GitHub

pragma solidity ^0.4.18;

/// auth.sol -- widely-used access control pattern for Ethereum

contract DSAuthority { function canCall( address src, address dst, bytes4 sig ) constant returns (bool); }

contract DSAuthEvents { event LogSetAuthority (address indexed authority); event LogSetOwner (address indexed owner); }

contract DSAuth is DSAuthEvents { DSAuthority public authority; address public owner;

function DSAuth() {
    owner = msg.sender;
    LogSetOwner(msg.sender);
}

function setOwner(address owner_)
    auth
{
    owner = owner_;
    LogSetOwner(owner);
}

function setAuthority(DSAuthority authority_)
    auth
{
    authority = authority_;
    LogSetAuthority(authority);
}

modifier auth {
    assert(isAuthorized(msg.sender, msg.sig));
    _;
}

function isAuthorized(address src, bytes4 sig) internal returns (bool) {
    if (src == address(this)) {
        return true;
    } else if (src == owner) {
        return true;
    } else if (authority == DSAuthority(0)) {
        return false;
    } else {
        return authority.canCall(src, this, sig);
    }
}

}

/// note.sol -- the `note' modifier, for logging calls as events

contract DSNote { event LogNote( bytes4 indexed sig, address indexed guy, bytes32 indexed foo, bytes32 indexed bar, uint wad, bytes fax ) anonymous;

modifier note {
    bytes32 foo;
    bytes32 bar;

    assembly {
        foo := calldataload(4)
        bar := calldataload(36)
    }

    LogNote(msg.sig, msg.sender, foo, bar, msg.value, msg.data);

    _;
}

}

/// stop.sol -- mixin for enable/disable functionality

contract DSStop is DSNote, DSAuth {

bool public stopped;

modifier stoppable {
    assert (!stopped);
    _;
}
function stop() auth note {
    stopped = true;
}
function start() auth note {
    stopped = false;
}

}

// Token standard API // https://github.com/ethereum/EIPs/issues/20

contract ERC20 { function totalSupply() constant returns (uint supply); function balanceOf( address who ) constant returns (uint value); function allowance( address owner, address spender ) constant returns (uint _allowance);

function transfer( address to, uint value) returns (bool ok);
function transferFrom( address from, address to, uint value) returns (bool ok);
function approve( address spender, uint value ) returns (bool ok);

event Transfer( address indexed from, address indexed to, uint value);
event Approval( address indexed owner, address indexed spender, uint value);

}

/// math.sol -- mixin for inline numerical wizardry

contract DSMath {

/*
standard uint256 functions
 */

function add(uint256 x, uint256 y) constant internal returns (uint256 z) {
    assert((z = x + y) >= x);
}

function sub(uint256 x, uint256 y) constant internal returns (uint256 z) {
    assert((z = x - y) <= x);
}

function mul(uint256 x, uint256 y) constant internal returns (uint256 z) {
    z = x * y;
    assert(x == 0 || z / x == y);
}

function div(uint256 x, uint256 y) constant internal returns (uint256 z) {
    z = x / y;
}

function min(uint256 x, uint256 y) constant internal returns (uint256 z) {
    return x <= y ? x : y;
}
function max(uint256 x, uint256 y) constant internal returns (uint256 z) {
    return x >= y ? x : y;
}

/*
uint128 functions (h is for half)
 */


function hadd(uint128 x, uint128 y) constant internal returns (uint128 z) {
    assert((z = x + y) >= x);
}

function hsub(uint128 x, uint128 y) constant internal returns (uint128 z) {
    assert((z = x - y) <= x);
}

function hmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
    z = x * y;
    assert(x == 0 || z / x == y);
}

function hdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
    z = x / y;
}

function hmin(uint128 x, uint128 y) constant internal returns (uint128 z) {
    return x <= y ? x : y;
}
function hmax(uint128 x, uint128 y) constant internal returns (uint128 z) {
    return x >= y ? x : y;
}


/*
int256 functions
 */

function imin(int256 x, int256 y) constant internal returns (int256 z) {
    return x <= y ? x : y;
}
function imax(int256 x, int256 y) constant internal returns (int256 z) {
    return x >= y ? x : y;
}

/*
WAD math
 */

uint128 constant WAD = 10 ** 18;

function wadd(uint128 x, uint128 y) constant internal returns (uint128) {
    return hadd(x, y);
}

function wsub(uint128 x, uint128 y) constant internal returns (uint128) {
    return hsub(x, y);
}

function wmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
    z = cast((uint256(x) * y + WAD / 2) / WAD);
}

function wdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
    z = cast((uint256(x) * WAD + y / 2) / y);
}

function wmin(uint128 x, uint128 y) constant internal returns (uint128) {
    return hmin(x, y);
}
function wmax(uint128 x, uint128 y) constant internal returns (uint128) {
    return hmax(x, y);
}

/*
RAY math
 */

uint128 constant RAY = 10 ** 27;

function radd(uint128 x, uint128 y) constant internal returns (uint128) {
    return hadd(x, y);
}

function rsub(uint128 x, uint128 y) constant internal returns (uint128) {
    return hsub(x, y);
}

function rmul(uint128 x, uint128 y) constant internal returns (uint128 z) {
    z = cast((uint256(x) * y + RAY / 2) / RAY);
}

function rdiv(uint128 x, uint128 y) constant internal returns (uint128 z) {
    z = cast((uint256(x) * RAY + y / 2) / y);
}

function rpow(uint128 x, uint64 n) constant internal returns (uint128 z) {
    // This famous algorithm is called "exponentiation by squaring"
    // and calculates x^n with x as fixed-point and n as regular unsigned.
    //
    // It's O(log n), instead of O(n) for naive repeated multiplication.
    //
    // These facts are why it works:
    //
    //  If n is even, then x^n = (x^2)^(n/2).
    //  If n is odd,  then x^n = x * x^(n-1),
    //   and applying the equation for even x gives
    //    x^n = x * (x^2)^((n-1) / 2).
    //
    //  Also, EVM division is flooring and
    //    floor[(n-1) / 2] = floor[n / 2].

    z = n % 2 != 0 ? x : RAY;

    for (n /= 2; n != 0; n /= 2) {
        x = rmul(x, x);

        if (n % 2 != 0) {
            z = rmul(z, x);
        }
    }
}

function rmin(uint128 x, uint128 y) constant internal returns (uint128) {
    return hmin(x, y);
}
function rmax(uint128 x, uint128 y) constant internal returns (uint128) {
    return hmax(x, y);
}

function cast(uint256 x) constant internal returns (uint128 z) {
    assert((z = uint128(x)) == x);
}

}

/// base.sol -- basic ERC20 implementation

contract DSTokenBase is ERC20, DSMath { uint256 _supply; mapping (address => uint256) _balances; mapping (address => mapping (address => uint256)) _approvals;

function DSTokenBase(uint256 supply) {
    _balances[msg.sender] = supply;
    _supply = supply;
}

function totalSupply() constant returns (uint256) {
    return _supply;
}
function balanceOf(address src) constant returns (uint256) {
    return _balances[src];
}
function allowance(address src, address guy) constant returns (uint256) {
    return _approvals[src][guy];
}

function transfer(address dst, uint wad) returns (bool) {
    assert(_balances[msg.sender] >= wad);
    
    _balances[msg.sender] = sub(_balances[msg.sender], wad);
    _balances[dst] = add(_balances[dst], wad);
    
    Transfer(msg.sender, dst, wad);
    
    return true;
}

function transferFrom(address src, address dst, uint wad) returns (bool) {
    assert(_balances[src] >= wad);
    assert(_approvals[src][msg.sender] >= wad);
    
    _approvals[src][msg.sender] = sub(_approvals[src][msg.sender], wad);
    _balances[src] = sub(_balances[src], wad);
    _balances[dst] = add(_balances[dst], wad);
    
    Transfer(src, dst, wad);
    
    return true;
}

function approve(address guy, uint256 wad) returns (bool) {
    _approvals[msg.sender][guy] = wad;
    
    Approval(msg.sender, guy, wad);
    
    return true;
}

}

/// token.sol -- ERC20 implementation with minting and burning

contract DSToken is DSTokenBase(0), DSStop {

bytes32  public  symbol;
uint256  public  decimals = 18; // standard token precision. override to customize

function DSToken(bytes32 symbol_) {
    symbol = symbol_;
}

function transfer(address dst, uint wad) stoppable note returns (bool) {
    return super.transfer(dst, wad);
}
function transferFrom(
    address src, address dst, uint wad
) stoppable note returns (bool) {
    return super.transferFrom(src, dst, wad);
}
function approve(address guy, uint wad) stoppable note returns (bool) {
    return super.approve(guy, wad);
}

function push(address dst, uint128 wad) returns (bool) {
    return transfer(dst, wad);
}
function pull(address src, uint128 wad) returns (bool) {
    return transferFrom(src, msg.sender, wad);
}

function mint(uint128 wad) auth stoppable note {
    _balances[msg.sender] = add(_balances[msg.sender], wad);
    _supply = add(_supply, wad);
}
function burn(uint128 wad) auth stoppable note {
    _balances[msg.sender] = sub(_balances[msg.sender], wad);
    _supply = sub(_supply, wad);
}

// Optional token name

bytes32   public  name = "";

function setName(bytes32 name_) auth {
    name = name_;
}

}

contract WarmWalletEvents { event LogSetWithdrawer (address indexed withdrawer); event LogSetWithdrawLimit (address indexed sender, uint value); event LogSetOwner(address indexed _owner); }

contract WarmWallet is WarmWalletEvents{

DSToken public key;
address public hotWallet;
address public coldWallet;

//@note
address public withdrawer;
uint public withdrawLimit;
uint256 public lastWithdrawTime;
address public owner;
bool public paused;

modifier onlyWithdrawer {
    require(msg.sender == withdrawer);
    _;
}

modifier onlyOwner {
    require(msg.sender == owner);
    _;
}

modifier notPaused {
    require(!paused);
    _;
}

// overrideable for easy testing
function time() public constant returns (uint) {
    return now;
}

function WarmWallet(DSToken _key, address _hot, address _cold, address _withdrawer, uint _limit) public {
    require(_key != address(0) );
    require(_hot != address(0) );
    require(_cold != address(0) );
    require(_withdrawer != address(0) );
    require(_limit > 0);

    require(_key != _hot);
    require(_key != _cold);
    require(_key != _withdrawer);

    key = _key;
    hotWallet = _hot;
    coldWallet = _cold;

    withdrawer = _withdrawer;
    withdrawLimit = _limit;
    lastWithdrawTime = 0;

    owner = msg.sender;
    paused = false;
}

function forwardToHotWallet(uint _amount) public notPaused onlyWithdrawer {
    require(_amount > 0);
    uint _time = time();
    require(_time > (lastWithdrawTime + 24 hours));

    uint amount = _amount;
    if (amount > withdrawLimit) {
        amount = withdrawLimit;
    }

    lastWithdrawTime = _time;
    key.transfer(hotWallet, amount);
}

function restoreToColdWallet(uint _amount) public onlyWithdrawer {
    require(_amount > 0);
    key.transfer(coldWallet, _amount);
}

function setWithdrawer(address _withdrawer) public onlyOwner {
    require(_withdrawer != address(0) );

    withdrawer = _withdrawer;
    LogSetWithdrawer(_withdrawer);
}

function setOwner(address _owner) public onlyOwner {
    owner = _owner;
    LogSetOwner(_owner);
}

function setWithdrawLimit(uint _limit) public onlyOwner {
    require(_limit > 0);

    withdrawLimit = _limit;
    LogSetWithdrawLimit(msg.sender, _limit);
}


function pauseStart() public onlyOwner {
    paused = true;
}

function pauseEnd() public onlyOwner {
    paused = false;
}

// @notice This method can be used by the controller to extract mistakenly
//  sent tokens to this contract.
// @param dst The address that will be receiving the tokens
// @param wad The amount of tokens to transfer
// @param _token The address of the token contract that you want to recover
function transferTokens(address dst, uint wad, address _token) public onlyWithdrawer {
    require(_token != address(key));
    if (wad > 0) {
        ERC20 token = ERC20(_token);
        token.transfer(dst, wad);
    }
}

}