Skip to content

Commit

Permalink
Merge branch 'ERC20EscrowToPayV1' into escrow-payment-processor
Browse files Browse the repository at this point in the history
  • Loading branch information
Dadogg80 committed Nov 18, 2021
2 parents a9fa16c + 305fcf5 commit 06260ba
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 16 deletions.
46 changes: 31 additions & 15 deletions packages/smart-contracts/src/contracts/ERC20EscrowToPay.sol
Expand Up @@ -109,7 +109,7 @@ contract ERC20EscrowToPay {
event RevertedEmergencyClaim(bytes indexed paymentReference);

/**
* @notice Emitted when _withdraw "to payee" has been executed.
* @notice Emitted when transaction to and from the escrow has been executed.
* @param tokenAddress Address of the ERC20 token smart contract.
* @param to Address to the payment issuer, alias payee.
* @param amount Amount transfered.
Expand Down Expand Up @@ -189,9 +189,10 @@ contract ERC20EscrowToPay {
}

/**
* @notice Locks the request funds for 12 months and cancel any emergency claim.
* @notice Locks the request funds for the payer to recover them
* after 12 months and cancel any emergency claim.
* @param _paymentRef Reference of the Invoice related.
* @dev Uses modifiers OnlyPayer and IsNotFrozen.
* @dev Uses modifiers OnlyPayer, IsInEscrow and IsNotFrozen.
* @dev unlockDate is set with block.timestamp + twelve months..
*/
function freezeRequest(bytes memory _paymentRef)
Expand All @@ -216,7 +217,7 @@ contract ERC20EscrowToPay {
/**
* @notice Closes an open escrow and pays the request to payee.
* @param _paymentRef Reference of the related Invoice.
* @dev Uses OnlyPayer, modifiers IsInEscrow, IsNOtInEmergencyState and IsNotFrozen.
* @dev Uses OnlyPayer, IsInEscrow, IsNotInEmergencyState and IsNotFrozen.
*/
function payRequestFromEscrow(bytes memory _paymentRef)
external
Expand All @@ -231,7 +232,7 @@ contract ERC20EscrowToPay {
/**
* @notice Allows the payee to initiate an emergency claim after a six months lockperiod .
* @param _paymentRef Reference of the related Invoice.
* @dev Uses modifiers IsInEscrow, IsNotFrozen.
* @dev Uses modifiers OnlyPayee, IsInEscrow, IsNotInEmergencyState and IsNotFrozen.
*/
function initiateEmergencyClaim(bytes memory _paymentRef)
external
Expand All @@ -249,7 +250,7 @@ contract ERC20EscrowToPay {
/**
* @notice Allows the payee claim funds after a six months emergency lockperiod .
* @param _paymentRef Reference of the related Invoice.
* @dev Uses modifiers IsInEscrow, IsNotFrozen.
* @dev Uses modifiers OnlyPayee, IsInEscrow and IsNotFrozen.
*/
function completeEmergencyClaim(bytes memory _paymentRef)
external
Expand All @@ -268,10 +269,10 @@ contract ERC20EscrowToPay {
require(_withdraw(_paymentRef, requestMapping[_paymentRef].payee), "Withdraw failed!");
}

/**
/**
* @notice Reverts the emergencyState to false and cancels emergencyClaim.
* @param _paymentRef Reference of the Invoice related.
* @dev Uses modifiers OnlyPayer and IsNotFrozen.
* @dev Uses modifiers OnlyPayer, IsInEscrow and IsNotFrozen.
* @dev Resets emergencyState to false and emergencyClaimDate to zero.
*/
function revertEmergencyClaim(bytes memory _paymentRef)
Expand All @@ -291,7 +292,7 @@ contract ERC20EscrowToPay {
* @notice Refunds to payer after twelve months and delete the escrow.
* @param _paymentRef Reference of the Invoice related.
* @dev requires that the request .isFrozen = true and .unlockDate to
* be lower or equal to block.timestamp.
* be lower or equal to block.timestamp.
*/
function refundFrozenFunds(bytes memory _paymentRef)
external
Expand All @@ -306,7 +307,7 @@ contract ERC20EscrowToPay {
require(_withdraw(_paymentRef, requestMapping[_paymentRef].payer), "Withdraw Failed!");
}

/**
/**
* @notice Withdraw the funds from the escrow.
* @param _paymentRef Reference of the related Invoice.
* @param _receiver Receiving address.
Expand All @@ -324,13 +325,18 @@ contract ERC20EscrowToPay {
require(_receiver != address(0), "ZERO adddress");
require(requestMapping[_paymentRef].amount > 0, "ZERO Amount");

IERC20 requestedToken = IERC20(requestMapping[_paymentRef].tokenAddress);

uint256 _amount = requestMapping[_paymentRef].amount;
requestMapping[_paymentRef].amount = 0;

IERC20(requestMapping[_paymentRef].tokenAddress).approve(address(paymentProxy), _amount);


// Checks if the requestedToken is allowed to spend.
if (requestedToken.allowance(address(this),address(paymentProxy)) < _amount) {
approvePaymentProxyToSpend(address(requestedToken));
}

paymentProxy.transferFromWithReferenceAndFee(
requestMapping[_paymentRef].tokenAddress,
address(requestedToken),
_receiver,
_amount,
_paymentRef,
Expand All @@ -343,8 +349,18 @@ contract ERC20EscrowToPay {
assert(!requestMapping[_paymentRef].emergencyState);

delete requestMapping[_paymentRef];

return true;
}

/**
* @notice Authorizes the proxy to spend a new request currency (ERC20).
* @param _erc20Address Address of an ERC20 used as the request currency.
*/
function approvePaymentProxyToSpend(address _erc20Address) public {
IERC20 erc20 = IERC20(_erc20Address);
uint256 max = 2**256 - 1;
erc20.safeApprove(address(paymentProxy), max);
}

}
16 changes: 15 additions & 1 deletion packages/smart-contracts/test/contracts/ERC20EscrowToPay.test.ts
Expand Up @@ -22,6 +22,8 @@ describe("Contract: ERC20EscrowToPay", () => {
const referenceExample6 = '0xffff';
const referenceExample7 = '0xaabb';
const referenceExample8 = '0xaacc';
const referenceExample9 = '0xaadd';

let testERC20: Contract, erc20EscrowToPay: ERC20EscrowToPay, erc20FeeProxy: ERC20FeeProxy;
let owner: Signer, payer: Signer, payee: Signer, buidler: Signer;
let payerAddress: string, payeeAddress: string, feeAddress: string, erc20EscrowToPayAddress: string;
Expand Down Expand Up @@ -151,7 +153,7 @@ describe("Contract: ERC20EscrowToPay", () => {
it("Should set to frozen w/ lockperiod, cancel emergency claim and emit event.", async () => {
await testERC20.connect(payer).approve(erc20EscrowToPayAddress, 2002);
await erc20EscrowToPay.connect(payer).payEscrow(testERC20.address, payeeAddress, 2000, referenceExample7, 2, feeAddress);
await erc20EscrowToPay.connect(payee).initiateEmergencyClaim(referenceExample7)
await erc20EscrowToPay.connect(payee).initiateEmergencyClaim(referenceExample7);

expect(await erc20EscrowToPay.connect(payer).freezeRequest(referenceExample7))
.to.emit(erc20EscrowToPay, "RequestFrozen")
Expand All @@ -168,6 +170,18 @@ describe("Contract: ERC20EscrowToPay", () => {

expect(erc20EscrowToPay.connect(payer).refundFrozenFunds(referenceExample8)).to.be.reverted;
});
it("Should revert if try to execute EmergencyClaim while request is frozen", async () => {
await testERC20.connect(payer).approve(erc20EscrowToPayAddress, 2002);
await erc20EscrowToPay.connect(payer).payEscrow(testERC20.address, payeeAddress, 2000, referenceExample9, 2, feeAddress);
await erc20EscrowToPay.connect(payer).freezeRequest(referenceExample9);

const requestMapping = await erc20EscrowToPay.connect(payer).requestMapping(referenceExample9);

// Make sure the request to be frozen.
expect(requestMapping.isFrozen).to.be.true;
// Expect the call to be reverted.
expect(erc20EscrowToPay.connect(payee).initiateEmergencyClaim(referenceExample9)).to.be.reverted;
});
});
});

0 comments on commit 06260ba

Please sign in to comment.