Tadle
is a Pre-Market
protocol that allows users to create offers for selling and/or buying point tokens in specific trading environments called marketplaces
. When users finish their trading agendas, and when the marketplace
reaches specific settlement conditions, sellers will settle the bought point tokens to the corresponding buyers. However, when settling the points, the receivers get actual collateral tokens accredited, instead of points, which can result in the whole protocol being drained, when these funds are withdrawn, as collateral tokens are usually represented by multiple point tokens.
There are two types of flows in Tadle
:
Alice creates an ASK
offer + BID
stock, to sell x
amount of points. Alice will also deposit a proper amount of ERC20
collateral token, based on the provided collateral rate
to make the offer more lucrative. Bob sees this offer and decides to accept it. He will create a taker
for Alice's offer, by creating a BID
stock and depositing the required collateral for the points. After a certain amount of time (after TGE or similar), the marketplace
will change its status to AskSettling
and Bob will expect Alice to settle the points he has bought (if she does not, then Bob gets Alice's collateral). Alice will invoke DeliveryPlace::settleAskMaker(...)
with her offer's address, which will debit the required point tokens from her account, and she will be accredited with the corresponding deposit made by Bob. Bob, on the other hand, will call DeliveryPlace::closeBidTaker(...)
with the address of his BID
stock and will be accredited with the promised tokens.
Bob creates a BID
offer + ASK
stock, to buy x
amount of points. Again, Bob will deposit collateral based on a set rate, to try and find a seller. Alice sees the offer and accepts it. She will create a taker
, and will create an ASK
stock, depositing collateral, so that Bob can be assured, that he won't be scammed if Alice does not have the required points. After a certain amount of time (after TGE or similar), the marketplace
will change its status to AskSettling
and Bob will expect Alice to settle her points to him. Alice will invoke DeliveryPlace::settleAskTaker(...)
which will debit the point tokens from her account and will set it as available for withdrawal for Bob. He will then call DeliveryPlace::closeBidOffer(...)
in case any points were not settled, to receive compensation.
However, both flows have serious flaws, as both DeliveryPlace::closeBidTaker(...)
and DeliveryPlace::settleAskTaker(...)
use the collateral token address when assigning the points revenue to the buyers, allowing them to withdraw the collateral token instead of the point token.
The below PoC shows how the exploit can occur. I have fixed the PreMarkets.sol
contract name as it was PreMarktes
.For reference, I have added a helper function in TokenManager.sol
:
It can be run by adding the snippets in PreMarkets.t.sol and running forge test --mt testUserDrainsCollateral -vv
. I am using the following setup for the tests:
\
Users can withdraw all collateral funds from the protocol.
Manual review
Set the proper point token address, instead of the collateral token address in DeliveryPlace::closeBidTaker(...)
and DeliveryPlace::settleAskTaker(...)
.
Valid high severity, In `settleAskTaker/closeBidTaker`, by assigning collateral token to user balance instead of point token, if collateral token is worth more than point, this can cause stealing of other users collateral tokens within the CapitalPool contract, If the opposite occurs, user loses funds based on the points they are supposed to receive
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.