Skip to content

Instantly share code, notes, and snippets.

@dshulyak
Last active April 2, 2018 06:27
Show Gist options
  • Save dshulyak/cee4fd86471c7d6666112c06bfb577c4 to your computer and use it in GitHub Desktop.
Save dshulyak/cee4fd86471c7d6666112c06bfb577c4 to your computer and use it in GitHub Desktop.
protected payments for service model
pragma solidity 0.4.21;
import './ecrecovery.sol';
contract Payments {
event LogExit(address recepient, uint256 value, uint id);
struct Exit {
address recipient;
uint256 value;
uint256 timestamp;
}
mapping(address => uint256) public deposits;
mapping(address => mapping(uint => bool)) public nonces;
mapping(uint => Exit) public exits;
uint currentExit;
function Payments() public {}
function deposit() payable public {
// overflow check
require(deposits[msg.sender] + msg.value > deposits[msg.sender]);
deposits[msg.sender] += msg.value;
}
function withdraw(uint256 value) public{
exits[currentExit] = Exit(msg.sender, value, block.timestamp);
emit LogExit(msg.sender, value, currentExit);
currentExit++;
}
// two days window required for a receiver to claim a payment
function finalizeWithdraw(uint id) public {
require(exits[id].value != 0);
uint256 twoDaysOld = block.timestamp - 2 days;
require(exits[id].timestamp < twoDaysOld);
require(deposits[exits[id].recipient] >= exits[id].value);
uint256 value = exits[id].value;
exits[id].value = 0;
exits[id].recipient.transfer(value);
}
function claimPayment(uint256 total, uint256 price, uint nonce, address receiver, bytes sig) public {
address payer = ECRecovery.recover(
keccak256(
"\x19Ethereum Signed Message:\n32",
keccak256(total, price, nonce, receiver)),
sig);
require(payer != address(0));
// TODO price should be a floating number
uint256 value = total * price;
// verify that payment for a given nonce wasn't claimed before
require(!nonces[payer][nonce]);
// verify that address has a deposit higher than promised payment
// also protects against underflow
require(deposits[payer] >= value);
nonces[payer][nonce] = true;
deposits[payer] -= value;
receiver.transfer(value);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment