Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- pragma solidity ^0.4.19;
- contract Vault {
- address public hot; // Hot wallet key
- address public cold; // Cold wallet key
- uint public hot_coins; // Coins for hot wallet
- uint public cold_coins; // Coins for cold wallet
- uint public coldToHot_delay; // Time delay to move coins from cold to hot wallet
- uint public hotToWithdraw_delay; // Time delay to move coins from hot wallet to user
- bool public lockdown; // Only cold key can be used
- uint public request_counter;
- mapping (uint => uint) public requests;
- mapping (address => WithdrawalRequest[]) public withdrawals;
- modifier notLockDown {
- require(!lockdown);
- _;
- }
- struct WithdrawalRequest {
- uint coins;
- uint time;
- }
- // Hot address = All actions are time delayed (moving from cold to hot, moving from hot to user)
- // Cold address = All actions are instant (moving from cold to hot wallet)
- // Cold to Hot Timer = How long it takes to move coins from hot to cold wallet (if authorised by hot wallet)
- // Hot to User Timer = How long it takes to move coins from hot wallet to user (if authorised by hot wallet)
- function Vault(address _hot, address _cold, uint _coldToHot, uint _hotToWithdraw) public {
- hot = _hot;
- cold = _cold;
- coldToHot_delay = _coldToHot;
- hotToWithdraw_delay = _hotToWithdraw;
- lockdown = false;
- request_counter = block.number;
- }
- // Deposit coins into cold wallet
- function deposit() public payable notLockDown {
- cold_coins = cold_coins + msg.value;
- }
- // Only hot or cold key can use this function
- function requestMoveColdToHot(uint amount) public notLockDown {
- // Can we perform the move?
- if(cold_coins >= amount) {
- // Only hot or cold wallet can authorise moving these coins
- // Hot = time delay
- // Cold = instant
- if(msg.sender == hot) {
- // Update cold balance!
- cold_coins = cold_coins - amount;
- // Need to enforce time delay (block.number + delay) and update coins that can be released in this future block
- requests[block.number + coldToHot_delay] = requests[block.number + coldToHot_delay] + amount;
- } else if(msg.sender == cold) {
- // No time delay for cold wallet!
- cold_coins = cold_coins - amount;
- hot_coins = hot_coins + amount;
- }
- }
- }
- // Confirm moving coins from cold to hot up to the previous block
- function completeMoveColdToHot() public notLockDown {
- // Only hot or cold wallet are authorised to update counter
- if(msg.sender == cold || msg.sender == hot) {
- // Go through each request that is now *valid* and update hot wallet balance
- for(uint i=request_counter; i<=block.number; i++) {
- // Update hot coins (and deduct from requests).
- uint amount = requests[i];
- requests[i] = 0;
- hot_coins = hot_coins + amount;
- // TODO: Chek remaining gas - stop if we are getting too low.
- }
- // Last number we checked was block.number
- // TODO: Update when dealing with remaining gas issue
- request_counter = block.number;
- }
- }
- // Hot wallet can authorise sending coins to a user (a time delay is incorporated)
- function authoriseWithdraw(address user, uint amount) public notLockDown {
- // We have enough coins for request; and only the hot wallet can call this function
- if(hot_coins >= amount && msg.sender == hot) {
- // deduct balance
- hot_coins = hot_coins - amount;
- // Create request for the requested coins + the delay before it is allowed
- WithdrawalRequest memory withdraw = WithdrawalRequest(amount, block.number + hotToWithdraw_delay);
- // Push new withdraw request for the specified user
- withdrawals[user].push(withdraw);
- }
- }
- // Users can withdraw their coins
- function withdraw() public notLockDown {
- uint towithdraw = 0;
- // Check if there are coins to send this user
- for(uint i=0; i<withdrawals[msg.sender].length; i++) {
- // Is this withdrawal now valid?
- if(withdrawals[msg.sender][i].time <= block.number) {
- // Awesome! Record coins to send (and empty list)
- uint amount = withdrawals[msg.sender][i].coins;
- withdrawals[msg.sender][i].coins = 0;
- withdrawals[msg.sender][i].time = 0;
- towithdraw = towithdraw + amount;
- }
- }
- // Send user their coins!
- msg.sender.transfer(towithdraw);
- }
- // Lock down contract!
- function lockdown() public {
- if(msg.sender == hot || msg.sender == cold) {
- lockdown = true;
- }
- }
- // Cold wallet can authorise moving coins anywhere (i.e. our escape hatch)
- function withdrawFromLockDown(address newowner) public {
- // Must be cold wallet and in lock down mode
- require(msg.sender == cold);
- require(lockdown);
- // Send all coins to the new owner (as dictated by the cold wallet)
- newowner.transfer(this.balance);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement