0

Let's say I want to build a product that let companies settle cross-border payments for invoices using DAI (https://makerdao.com/en/dai/) as medium of exchange to ensure stable value of the transaction.

I already started building a Prototyp but got stuck at some point. The idea is the following:

  • Biller creates an invoice that is stored on a smart contract
  • Receiver interacts with dapp to settle payment in DAI to the smart contract
  • Smart contract act as custody and redirect payment to biller once the invoice is fully payed (Receiver can also pay partially)

I was already able to to the following:

  • Created a smart contract that let biller create and manage invoices
  • Created a ethers.js based dapp that let receivers:

    • unlock the usage of DAI token ("approve" function on DAI smart contract)

    • Settle payment (using transferFrom to send DAI tokens to smart contract)

However, that's where I'm stuck. The part that is missing:

  • Incoming payment from receiver is stored in smart contract

  • Smart contract run some function to trigger payment to biller (if invoice was fully payed)

The issue:

I came to understand that there are no ways to trigger my smart contract once the receiver sends the DAI token, thus the DAI token would be transfered to the smart contract but wouldn't trigger the smart contract logic to update the invoice status and forwarding payment to biller. Given this scenario, how could possible solutions look like?

0

One way to solve that using ERC20 is for the contract to call transferFrom, and on full payment to forward funds to recipient immediately

function payInvoice(uint id, uint amount) public {
    Invoice storage invoice = getInvoice(id);
    // Accept payment
    dai.transferFrom(msg.sender, address(this), amount);
    invoice.paid += amount;

    // If paid in full send payment to recipient
    if (invoice.paid >= invoice.total) {
        dai.transfer(invoice.recipient, invoice.total);
    }
}

Another option is for the function to generate an event, and leave the responsability to the recipient to withdraw funds

function payInvoice(uint id, uint amount) public {
    Invoice storage invoice = getInvoice(id);
    // Accept payment
    dai.transferFrom(msg.sender, address(this), amount);
    invoice.paid += amount;

    // If paid in full
    if (invoice.paid >= invoice.total) {
        // Notify recipient
        emit FullPayment(invoice.recipient, invoice.total);
    }
}

Now recipient has to withdraw funds

function withdrawInvoice(uint id, uint amount) public {
    Invoice storage invoice = getInvoice(id);
    if (invoice.paid >= invoice.total) {
        // Notify recipient
        dai.transfer(invoice.recipient, invoice.total);
    }
}

ERC20 doesn't provide a mechanism to notify a contract when it has received a payment. There's a new standard ERC-777 that provides such a mechanism but it requires a redeployment.

For ERC20 you can run a service that listen for Transfer events to your contract.

| improve this answer | |
  • Thanks – very helpful. One quetion: In your first example. If I trigger the transfer of DAI to the contract (dai.transferFrom(msg.sender, address(this), amount);) I probably cannot be sure the transfer will succeed at this time – right? – Nico E Nov 5 '19 at 9:58
  • If the sender didn't approve your contract or approve for a lower amount it will fail, but in that case the whole transaction will revert. If it has succeeded the tokens will be in the contract address. – Ismael Nov 5 '19 at 14:45
  • Just added an additional comment – Nico E Nov 6 '19 at 6:47
  • @NicoE I've edited my answer with a reply to your new question – Ismael Nov 6 '19 at 15:09
0

Just tried it with this one:

address dai = 0xC4375B7De8af5a38a93548eb8453a498222C4fF2;
dai.call.gas(999999)(abi.encodeWithSignature("transferFrom(address,address,uint256)", _from, _to, _amount));

But even if the Approved function with the smart contract address has been successfully running. I currently do get an error that says Out of gas.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.