Skip to content

Instantly share code, notes, and snippets.

@SerpentChris
Last active January 2, 2018 19:02
Show Gist options
  • Save SerpentChris/835df2a21c3fb9ebdcf80449b273c112 to your computer and use it in GitHub Desktop.
Save SerpentChris/835df2a21c3fb9ebdcf80449b273c112 to your computer and use it in GitHub Desktop.
HODL your tokens AND your ETH!
pragma solidity ^0.4.19;
// Copyright (c) 2017 Christian Calderon
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
interface ERC20 {
function transferFrom(address from, address to, uint tokens) public returns (bool success);
function transfer(address to, uint tokens) public returns (bool success);
}
contract HODL{
struct Deposit {
address token;
uint balance;
uint hodl_end;
}
address constant ETH = address(1);
mapping(address => Deposit[]) deposits;
event Withdrawal(address indexed token, uint indexed amount);
function myDeposits() public view returns (Deposit[]) {
// This function is only useful for UIs.
Deposit[] storage ds = deposits[msg.sender];
uint depositCount = 0;
uint length = ds.length;
uint i = 0;
while(i < length){
if(ds[i].token != 0){
depositCount += 1;
}
i += 1;
}
Deposit[] memory result = new Deposit[](depositCount);
i = 0;
uint j = 0;
while(i < length){
if(ds[i].token != 0){
result[j] = ds[i];
j += 1;
}
i += 1;
}
return result;
}
function hodl(address withdrawer, address token, uint amount, uint hodl_time) public payable returns (bool) {
require(uint(withdrawer) >> 160 == 0);
require(uint(token) >> 160 == 0);
require(amount > 0);
require(hodl_time > 0);
uint hodl_end = block.timestamp + hodl_time;
assert(hodl_end > block.timestamp);
if(token != ETH){
require(msg.value == 0);
require(ERC20(token).transferFrom(msg.sender, address(this), amount));
} else {
require(msg.value == amount);
}
Deposit[] storage ds = deposits[withdrawer];
uint i = 0;
while(i < ds.length){
if(ds[i].token == address(0)){
ds[i] = Deposit(token, amount, hodl_end);
break;
}
i += 1;
}
if(i == ds.length){
ds.push(Deposit(token, amount, hodl_end));
}
return true;
}
function withdraw() public {
Deposit[] storage ds = deposits[msg.sender];
uint length = ds.length;
address[] memory tokens = new address[](length);
uint[] memory amounts = new uint[](length);
uint tokens_found = 0;
uint i = 0;
uint time = block.timestamp;
while(i < length){
if(ds[i].hodl_end > time){
i += 1;
continue;
}
uint j = 0;
while(j < tokens_found){
if(tokens[j] == ds[i].token){
break;
}
j += 1;
}
if(j == tokens_found){
tokens_found += 1;
tokens[j] = ds[i].token;
}
amounts[j] += ds[i].balance;
delete ds[i].token;
delete ds[i].balance;
delete ds[i].hodl_end;
i += 1;
}
i = 0;
while(i < tokens_found){
if(tokens[i] != ETH){
ERC20(tokens[i]).transfer(msg.sender, amounts[i]);
} else {
msg.sender.transfer(amounts[i]);
}
Withdrawal(tokens[i], amounts[i]);
i += 1;
}
i = length - 1;
uint new_length = length;
while(i > 0){
if(ds[i].token != 0){
break;
}
new_length -= 1;
i -= 1;
}
if(new_length != length){
ds.length = new_length;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment