Please see attached Tenderly stack trace:
https://dashboard.tenderly.co/shared/simulation/86e27f67-6f7e-4122-83da-d43f455fb57a
I'm not sure why transferfrom is failing even through I have granted uint256 unlimited allowance to the contract withdrawing my USDT.
Contract code (Vyper)
@external
def swap(
_from: address,
_to: address,
_amount: uint256,
_minout: uint256,
_order_id: Bytes[10],
_tofiat: bool,
_totopup: bool,
) -> uint256:
sanctioned: bool = Chainanalysis(0x40C57923924B5c5c5455c48D93317139ADDaC8fb).isSanctioned(msg.sender)
assert sanctioned != True, "sanctioned"
assert self.paused == False, "paused"
if (_totopup):
assert _to == USDC_eth, "USDC"
if (_tofiat):
assert _to == USDC_eth, "USDC"
ERC20(_from).transferFrom(msg.sender,self,_amount)
ERC20(_from).approve(UNISWAP, _amount)
balance_before: uint256 = ERC20(_to).balanceOf(self)
result: Bytes[32] = raw_call(
UNISWAP,
concat(
method_id("exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160))"),
convert(_from, bytes32),
convert(_to, bytes32),
convert(3000, bytes32), #pool fee
convert(self, bytes32), #recipient
convert(block.timestamp, bytes32), #deadline
convert(_amount, bytes32),
convert(_minout, bytes32),
convert(0, bytes32), #sqrtPriceLimitX96
),
max_outsize=32
)
output: uint256 = convert(result, uint256)
balance_after: uint256 = ERC20(_to).balanceOf(self)
assert balance_after - balance_before == output, "not balanced"
assert output >= _minout, "too little"
if (_totopup):
fees: uint256 = output * self.fee_topup/10000
ERC20(_to).transfer(profits,fees)
log TopedUp(msg.sender,_amount,output,_order_id)
return output
elif(_tofiat):
fees: uint256 = output * self.fee_fiat/10000
ERC20(_to).transfer(profits,fees)
if (self.topartner):
ERC20(USDC_eth).transfer(self.partner_wallet,_amount-fees)
log Success(msg.sender,_amount,output,_order_id)
return output
else:
fees: uint256 = output * self.fee_swap/10000
if (_to == USDC_eth):
ERC20(_to).transfer(profits,fees)
ERC20(_to).transfer(msg.sender,output-fees)
else:
ERC20(_to).transfer(msg.sender,output-fees)
new_output: uint256 = self.to_usdc(_to,fees)
ERC20(USDC_eth).transfer(profits,new_output)
log Success(msg.sender,_amount,output,_order_id)
return output
05/11/2023 updated:
Based on feedback provided by @Vas Trek have updated this to check if allowance is already set, if it is, to zero allowance and to reset it.
Issue still persists.
allowance: uint256 = ERC20(_from).allowance(self,UNISWAP)
if (allowance == 0):
ERC20(_from).approve(UNISWAP, _amount)
else:
ERC20(_from).approve(UNISWAP, 0) ERC20(_from).approve(UNISWAP,_amount)
Kind regards,