Skip to content

Instantly share code, notes, and snippets.

@janoschp
Created January 26, 2022 16:48
Show Gist options
  • Save janoschp/d7de82d6d5dcb72162ef6b65f43ddf9e to your computer and use it in GitHub Desktop.
Save janoschp/d7de82d6d5dcb72162ef6b65f43ddf9e to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.11+commit.d7f03943.js&optimize=false&runs=200&gist=
//SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
contract CalculateHash {
function calculateHash(uint key) external pure returns (bytes32) {
return keccak256(abi.encode(key));
}
}
//SPDX-License-Identifier: MIT
pragma solidity >=0.7.0 <0.9.0;
interface HTLStore {
// A Deposited event should be emitted after ether has been successfully
// deposited to the store.
event Deposited(address benefactor, bytes32 lock, uint amount, uint timeout);
// A Claimed event should be emitted after deposited ether has been
// successfully claimed from the store.
event Claimed(address beneficiary, bytes32 lock, uint key, uint amount);
// A Recovered event should be emitted after ether has been recovered by the
// initial benefactor.
event Recovered(address benefactor, bytes32 lock, uint amount);
// deposit should add the sent ether to the amount stored for the lock. The
// claim period timeout should be reset to now + duration.
function deposit(bytes32 lock, uint duration) external payable;
// claim should allow a holder of the correct pre-image key to withdraw the
// ether stored for the lock = keccak256(key) within the claim period.
function claim(uint key) external;
// recover should allow the initial depositor to recover the ether stored
// for the lock after the claim period has ended.
function recover(bytes32 lock) external;
}
struct DepositStruct {
address depositor;
bytes32 lock;
uint amount;
uint timeout;
bool claimedOrRecovered;
}
contract HTLStoreImplementation is HTLStore {
mapping(bytes32 => DepositStruct) lockToDepositMap;
// deposit should add the sent ether to the amount stored for the lock. The
// claim period timeout should be reset to now + duration.
function deposit(bytes32 lock, uint duration) override external payable {
DepositStruct memory currentDeposit = lockToDepositMap[lock];
require(!currentDeposit.claimedOrRecovered, "This deposit has already been claimed or recovered!");
require(msg.value > 0, "Please add some ether first!");
require(duration > 0, "The timeout has to be larger than 0!");
// Check if it is already in deposits and update the deposit:
if (currentDeposit.lock == lock) {
require(currentDeposit.depositor == msg.sender, "You are not the original depositor of this deposit!");
uint256 depositedAmount = msg.value;
uint256 newAmount = currentDeposit.amount + depositedAmount;
uint256 newTimeout = block.timestamp + duration;
currentDeposit.amount = newAmount;
currentDeposit.timeout = newTimeout;
lockToDepositMap[lock] = currentDeposit;
emit Deposited(msg.sender, lock, depositedAmount, newTimeout);
return;
}
//otherwise add a new one:
uint256 timeout = block.timestamp + duration;
lockToDepositMap[lock] = DepositStruct(msg.sender, lock, msg.value, timeout, false);
emit Deposited(msg.sender, lock, msg.value, timeout);
}
// claim should allow a holder of the correct pre-image key to withdraw the
// ether stored for the lock = keccak256(key) within the claim period.
function claim(uint key) override external {
bytes32 lock = keccak256(abi.encode(key));
DepositStruct memory currentDeposit = lockToDepositMap[lock];
require(currentDeposit.lock == lock, "Couldn't find a deposit with that key!");
require(currentDeposit.depositor != msg.sender, "You can't claim your own deposit!");
require(!currentDeposit.claimedOrRecovered, "Deposit has already been claimed or recovered!");
require(currentDeposit.amount > 0, "There no ether in this deposit!");
require(block.timestamp <= currentDeposit.timeout, "Timeout is over!");
currentDeposit.claimedOrRecovered = true;
lockToDepositMap[lock] = currentDeposit;
emit Claimed(msg.sender, currentDeposit.lock, key, currentDeposit.amount);
payable(msg.sender).transfer(currentDeposit.amount);
}
// recover should allow the initial depositor to recover the ether stored
// for the lock after the claim period has ended.
function recover(bytes32 lock) override external {
DepositStruct memory currentDeposit = lockToDepositMap[lock];
require(currentDeposit.lock == lock, "Couldn't find a deposit with that lock!");
require(currentDeposit.depositor == msg.sender, "You are not the original depositor of this deposit!");
require(!currentDeposit.claimedOrRecovered, "Deposit has already been claimed or recovered!");
require(currentDeposit.amount > 0, "There is no ether in the deposit!");
require(block.timestamp > currentDeposit.timeout, "Timeout is not over yet!");
currentDeposit.claimedOrRecovered = true;
lockToDepositMap[lock] = currentDeposit;
emit Recovered(msg.sender, lock, currentDeposit.amount);
payable(msg.sender).transfer(currentDeposit.amount);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment