feat: Sketch for OneTransferFromOnly.sol
Took 49 seconds
This commit is contained in:
77
foundry/src/OneTransferFromOnly.sol
Normal file
77
foundry/src/OneTransferFromOnly.sol
Normal file
@@ -0,0 +1,77 @@
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
pragma solidity ^0.8.26;
|
||||
|
||||
import "@interfaces/IExecutor.sol";
|
||||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||
import "@permit2/src/interfaces/IAllowanceTransfer.sol";
|
||||
|
||||
error TokenTransfer__AddressZero();
|
||||
|
||||
contract OneTransferFromOnly {
|
||||
using SafeERC20 for IERC20;
|
||||
|
||||
// this is a stupid name but the compiler was complaining that we already had a permit2 variable in TychoRouter
|
||||
IAllowanceTransfer public immutable permit2lal;
|
||||
uint256 private constant _TOKEN_IN_SLOT = 123;
|
||||
uint256 private constant _AMOUNT_IN_SLOT = 124;
|
||||
uint256 private constant _IS_PERMIT2_SLOT = 125;
|
||||
uint256 private constant _SENDER_SLOT = 126;
|
||||
uint256 private constant _IS_TRANSFER_EXECUTED_SLOT = 127;
|
||||
|
||||
constructor(address _permit2) {
|
||||
if (_permit2 == address(0)) {
|
||||
revert TokenTransfer__AddressZero();
|
||||
}
|
||||
permit2lal = IAllowanceTransfer(_permit2);
|
||||
}
|
||||
|
||||
function tstoreTransferFromInfo(
|
||||
address tokenIn,
|
||||
address amountIn,
|
||||
bool isPermit2,
|
||||
address sender
|
||||
) internal {
|
||||
assembly {
|
||||
tstore(_TOKEN_IN_SLOT, tokenIn)
|
||||
tstore(_AMOUNT_IN_SLOT, amountIn)
|
||||
tstore(_IS_PERMIT2_SLOT, isPermit2)
|
||||
tstore(_SENDER_SLOT, sender)
|
||||
tstore(_IS_TRANSFER_EXECUTED_SLOT, false)
|
||||
}
|
||||
}
|
||||
|
||||
function _transfer(address receiver)
|
||||
// we could pass the amount and address too and compare to what is in the slots?
|
||||
internal
|
||||
{
|
||||
address tokenIn;
|
||||
uint256 amount;
|
||||
bool isPermit2;
|
||||
address sender;
|
||||
bool isTransferExecuted;
|
||||
assembly {
|
||||
tokenIn := tload(_TOKEN_IN_SLOT)
|
||||
amount := tload(_AMOUNT_IN_SLOT)
|
||||
isPermit2 := tload(_IS_PERMIT2_SLOT)
|
||||
sender := tload(_SENDER_SLOT)
|
||||
isTransferExecuted := tload(_IS_TRANSFER_EXECUTED_SLOT)
|
||||
}
|
||||
if (isTransferExecuted) {
|
||||
return; // or revert?
|
||||
}
|
||||
|
||||
if (isPermit2) {
|
||||
// Permit2.permit is already called from the TychoRouter
|
||||
permit2lal.transferFrom(sender, receiver, uint160(amount), tokenIn);
|
||||
assembly {
|
||||
tstore(_IS_TRANSFER_EXECUTED_SLOT, true)
|
||||
}
|
||||
} else {
|
||||
// slither-disable-next-line arbitrary-send-erc20
|
||||
IERC20(tokenIn).safeTransferFrom(sender, receiver, amount);
|
||||
assembly {
|
||||
tstore(_IS_TRANSFER_EXECUTED_SLOT, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user