Signed Voucher Escrow

signed-voucher-escrow · conditional-settlement · 1623 B runtime · funds-movement

scores

source

pragma solidity ^0.8.13;

contract SignedVoucherEscrow {
    mapping(address => uint256) public deposits;
    mapping(bytes32 => bool) public used;

    event Claimed(address indexed payer, address indexed payee, uint256 amount, bytes32 indexed invoiceId);

    receive() external payable {
        deposits[msg.sender] += msg.value;
    }

    function claim(
        address payer,
        address payee,
        uint256 amount,
        bytes32 invoiceId,
        bytes calldata signature
    ) external {
        require(signature.length == 65, "len");
        bytes32 msgHash = keccak256(abi.encodePacked(
            "\x19Ethereum Signed Message:\n32",
            keccak256(abi.encodePacked(payer, payee, amount, invoiceId))
        ));
        address signer = ecrecover(msgHash, uint8(signature[64]), bytes32(signature[0:32]), bytes32(signature[32:64]));
        require(signer == payer, "sig");
        require(!used[invoiceId], "used");
        used[invoiceId] = true;
        uint256 bal = deposits[payer];
        require(bal >= amount, "bal");
        deposits[payer] = bal - amount;
        (bool ok, ) = payable(payee).call{value: amount}("");
        require(ok, "fail");
        emit Claimed(payer, payee, amount, invoiceId);
    }
}