Hi everyone, I’m Samrat Gupta, aka Sm4rty, an independent security researcher and smart contract auditor. In this blog post, I’m continuing my series of posts on audit findings review. In the previous post, we looked at the findings from the Kunji Finance audit. Today, we’ll be looking at the findings from one of my most challenging audits at Detectbox i.e. Payant Escrow.
Let's Start:
Before starting out. Let me give a brief description of Detectbox.
About DetectBox:
DetectBox is an emerging auditing marketplace for auditors and Projects. Unlike traditional auditing firms that keep auditors’ identities hidden, DetectBox promotes transparency. It allows projects and protocols to choose auditors independently to evaluate their work. This inclusive process ensures that experts from different backgrounds can contribute to the auditing process. The platform also helps us learn and collaborate with fellow auditors.
Check out their official Website for more info.
About Payant Escrow:
Payant is a platform that facilitates seamless invoicing, payment, and fund withdrawal processes for clients and contractors. It is built on the top of Rain Protocol.
The Payant project utilizes two primary contracts: the FlowFactory contract and the Flow contract. The FlowFactory contract is responsible for deploying instances of the Flow contract, which handle various invoice-related operations.
Check out the official website for more info about Payant.
Collaborations:
For this Audit, I was the Lead Auditor and I collaborated with Rohan Jha, an excellent auditor. 33Audits was assigned as Detect Warden for this audit, and I was grateful for the opportunity to work with them. It was a pleasure working with both Rohan and 33Audits.
Key Discoveries
In this blog, I will be sharing two High-Severity findings from the Payant Escrow. Check here for the full report.
The Challenges of Auditing the Payant Escrow
The Payant Escrow is built on the top of Rain Protocol. The contracts of the Payant are written in the Rain programming language. In order to audit the Payant Escrow, I had to learn Rain, Rain Protocol, and the Rain VM from scratch. This was a challenging task, but it was also a valuable learning experience.
Before getting into Vulnerability Let’s Understand How the Mediation Process works.
According to the Project, There’s a fee related to mediation that Payant will pay in advance. However, when the result of the dispute is implemented, Payant will take out the cut of the fee with no additional charge. Example: Invoice is $1000, the fee is $100. Side A wins and can claim the full amount. We will send $900 to side A and $100 to the wallet managing the Kleros integration.
Also, I created a mindmap of the basic contract flow for a better understanding of core functions:
H-01. The contractor can cancel the contract after mediation has been started leading to fund loss for the Protocol.
Vulnerability Details:
The Payant contract allows the contractor to cancel the contract after the mediation process has been started. There is a check that the mediation process can only be canceled by the Mediator. This can be exploited by the contractor to avoid paying the mediation fees, which are paid by the Payant in advance.
Code Snippet:
There is no check in the cancel contract script for if the mediation process has been started.
: ensure(equal-to(signer contractor)),
: ensure(equal-to(signedcontexthash datahash)),
: ensure(equal-to(context-column-hash<1>() datahash)),
: ensure(equal-to(operation cancel-operation)),
: ensure(is-zero(get(one))),
Proof of Concept (with Test case):
- A client and a contractor enter into a contract on the Payant Protocol.
- The contract includes a mediation clause that allows the parties to resolve disputes through mediation.
- The mediation process has started.
- The contractor cancels the contract after mediation has been started.
- The client receives the full amount of the contract without paying the mediation fees.
The Coded POC for the above bug can be found here.
H-02. Client can approve the Deliverables after mediation has been started leading to the fund loss for Protocol.
This issue is similar to the above. Instead of the contractor canceling the contract, the Client approves the deliverables and the contractor receives the amount.
Vulnerability Details:
The Payant contract allows the client to approve deliverables to the contractor after the mediation process has been started. There is a check that the mediation process can only be canceled by the Mediator. This can be exploited by the client to avoid paying the mediation fees, which are paid by the Payant protocol in advance.
Code Snippet:
There is no check in the “approve deliverables” contract for if the mediation process has been started.
: ensure(is-zero(get(one))), /** Ensure contract is not setteled */
: ensure(get(deliverables-flag)), /** Ensure deliverables are added */
: ensure(equal-to(client signer)), /** Ensure client is calling the function*/
: ensure(equal-to(datahash signedcontexthash)), /** Ensure contract is for same invoice using datahash */
: ensure(equal-to(signedcontexthash context-column-hash<1>())), /** Ensure signedContext is same as callerContext */
: ensure(equal-to(operationhash approve-deliverable-operation)), /** Script only for approve delivrables */
Proof of Concept (with Test case):
- A client and a contractor enter into a contract on the Payant Protocol.
- The contract includes a mediation clause that allows the parties to resolve disputes through mediation.
- The mediation process has started.
- The client approves the deliverables of the contractor after the mediation process has been started.
- The contractor receives the full amount of the contract without paying the mediation fees.
The Coded POC for the above bug can be found here.
Remediation
The Payant team has fixed both of these vulnerabilities by adding checks to the contracts to ensure that contracts cannot be canceled or deliverables cannot be approved after the mediation process has been started.
Apart from these, there were a some low, and Gas Optimization issues. You can have a look at the full audit report here.
Conclusion:
I would like to thank DetectBox for the opportunity to audit Payant Escrow. It was a great learning experience, and I’m glad that I could contribute to the security of the DeFi ecosystem.