Atomic Pull-Payment Settlement

atomic-pull-payment-settlement · conditional-settlement · 1287 B runtime · funds-movement

scores

source

pragma solidity ^0.8.13;

interface IERC20 {
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

contract AtomicPullPaymentSettlement {
    IERC20 public immutable token;
    address public immutable funder;
    bool private locked;

    event Settled(address indexed worker, address indexed funder, uint256 amount, bytes32 dataHash);

    constructor(address _token, address _funder) {
        token = IERC20(_token);
        funder = _funder;
    }

    modifier noReentrancy() {
        require(!locked, 'reentrant');
        locked = true;
        _;
        locked = false;
    }

    function settle(
        address worker,
        bytes calldata data,
        bytes32 expectedHash
    ) external noReentrancy returns (uint256 amount) {
        (bool ok, bytes memory ret) = worker.call(data);
        require(ok, 'worker failed');
        require(ret.length == 32, 'bad result length');
        require(keccak256(ret) == expectedHash, 'bad result');
        amount = abi.decode(ret, (uint256));
        require(token.transferFrom(funder, worker, amount), 'transfer failed');
        emit Settled(worker, funder, amount, expectedHash);
    }
}