The PuttyV2.fillOrder is a payable function that allows users to transfer native ETH when filling an order. The native ETH is only applicable when the baseAsset is equal to WETH AND during the following scenarios:
When transferring premium from taker to maker; OR
When transferring strike from taker to the PuttyV2 contract.
In all other circumstances, native ETH transfer is not applicable within the PuttyV2.fillOrder function. The following table summarises whether or not the four (4) key workflows within the PuttyV2.fillOrder function requires native ETH transfer:
Workflows
Accept or Require Native ETH Transfer?
Long Call
No
Short Call
Yes (For transfering native ETH premium from taker)
Long Put
Yes (For transferring native ETH strike from taker )
Short Put
Yes (For transfering native ETH premium from taker)
Thus, it is possible that the users accidentially attached non-zero Ether value to the transaction when calling PuttyV2.fillorder function when executing the Long Call workflow. Thus, the user's Ether will be locked within the contract without the ability to retrieve it.
function fillOrder(
Order memory order,
bytes calldata signature,
uint256[] memory floorAssetTokenIds
) public payable returns (uint256 positionId) {
Impact
User's Ether locked in the contract.
Recommended Mitigation Steps
It is recommended to reverts if msg.value > 0 for workflows or scenarios that Native ETH is not expected or required.
When the order.baseAsset is not equal to WETH AND `msg.value > 0 `, it should reverts.
Additionally, the Long Call workflow does not expect any native ETH to be sent. Therefore, if msg.value > 0, it should reverts.
function fillOrder(
Order memory order,
bytes calldata signature,
uint256[] memory floorAssetTokenIds
) public payable returns (uint256 positionId) {
// If baseAsset is not WETH, there shouldn't be any native ETH attached
if (order.baseAsset != weth && msg.value > 0) {
revert();
}
// If filling long call, there shouldn't be any native ETH attached
if (order.isLong && order.isCall && msg.value > 0) {
revert();
}
..SNIP..
Lines of code
https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L268
Vulnerability details
Proof-of-Concept
The
PuttyV2.fillOrder
is a payable function that allows users to transfer native ETH when filling an order. The native ETH is only applicable when thebaseAsset
is equal toWETH
AND during the following scenarios:PuttyV2
contract.In all other circumstances, native ETH transfer is not applicable within the
PuttyV2.fillOrder
function. The following table summarises whether or not the four (4) key workflows within thePuttyV2.fillOrder
function requires native ETH transfer:Thus, it is possible that the users accidentially attached non-zero Ether value to the transaction when calling
PuttyV2.fillorder
function when executing theLong Call
workflow. Thus, the user's Ether will be locked within the contract without the ability to retrieve it.https://github.com/code-423n4/2022-06-putty/blob/3b6b844bc39e897bd0bbb69897f2deff12dc3893/contracts/src/PuttyV2.sol#L268
Impact
User's Ether locked in the contract.
Recommended Mitigation Steps
It is recommended to reverts if
msg.value > 0
for workflows or scenarios that Native ETH is not expected or required.When the
order.baseAsset
is not equal toWETH
AND`msg.value > 0
`, it should reverts.Additionally, the
Long Call
workflow does not expect any native ETH to be sent. Therefore, ifmsg.value > 0
, it should reverts.