try to call erc20 token's transferFrom()
using assembly(to save some gas), code like this:
pragma solidity ^0.4.24;
contract TestAssemblyAndRevert {
function test(address from, address to, uint256 value) public {
// a standard erc20 token
address token = 0xedc2d4aca4f9b6a23904fbb0e513ea0668737643;
// call transferFrom() of token using assembly
assembly { // LineA
// keccak256('transferFrom(address,address,uint256)') & 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000
mstore(0, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
// calldatacopy(t, f, s) copy s bytes from calldata at position f to mem at position t
// copy from, to, value from calldata to memory
calldatacopy(4, 4, 96)
// call ERC20 Token contract transferFrom function
let result := call(gas, token, 0, 0, 100, 0, 32)
if eq(result, 1) {
return(0, 0)
}
//revert(0, 0); // LineB
}
revert("TOKEN_TRANSFER_FROM_ERROR"); // LineC
}
}
the token is a standard ERC20 token that when some spender trying to call transferFrom()
without enough allowance, it will revert, in our case, this line:
let result := call(gas, token, 0, 0, 100, 0, 32)
result
will be 0.
The thing surprise me is that when this happens, the transaction will use up all the gasLimit. why is that?
I tried several other cases, none of them will use up the gas:
- if I comment out the whole assembly code block, or
- if I keep the assembly code block, but comment out:
revert("TOKEN_TRANSFER_FROM_ERROR")
, LineC - if I comment out LineC, keep the assembly block and uncomment LineB