approve and transferFrom
ERC20 transfers from your wallet use transfer. Third parties (DEX routers, staking contracts) use transferFrom after you approve them for an allowance. The allowance is a per-(owner, spender) budget decremented on each pull until you approve again.
- First swap often needs approve + swap — two transactions unless using permit.
- approve(spender, 0) then approve(spender, amount) is the safe reset pattern on some tokens.
- increaseAllowance / decreaseAllowance avoid USDT-style front-running quirks.
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
function depositStake(IERC20 token, uint256 amount) external {
token.transferFrom(msg.sender, address(this), amount);
// user must have called token.approve(address(this), amount) first
}Infinite approvals
type(uint256).max approval means the spender never needs another approval. Convenient, dangerous: if the spender is exploited, all tokens of that type at your address can be drained. Prefer exact allowances, periodic revoke, or Permit2 with time bounds where integrators support it.
- Wallet UIs often default to unlimited — change to exact amount when possible.
- Revoke.cash and similar tools scan Approval events for your address.
- Compromised router upgrades can abuse old infinite approvals.
NFT approvals
ERC721 uses approve per tokenId or setApprovalForAll for an operator on every token you own. setApprovalForAll is powerful — marketplaces need it, but malicious sites abuse it. ERC1155 uses setApprovalForAll similarly for all ids in the contract.
- getApproved(tokenId) shows single-token approval.
- isApprovedForAll(owner, operator) gates marketplace listings.
- Revoke marketplace access when you stop trading.
Safe transfers
safeTransferFrom on ERC721/1155 checks IERC721Receiver.onERC721Received (or 1155 equivalent). Without it, contracts lacking a receiver hook could lock NFTs forever. OpenZeppelin _safeMint and safeTransferFrom enforce this on the receiving side.
- EOA recipients skip the callback — no gas overhead.
- Contracts must implement the receiver interface to accept safe transfers.
- Using transferFrom to contracts without a receiver is a common footgun.
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
// _safeMint and safeTransferFrom call _checkOnERC721ReceivedPermit and meta-transactions
EIP-2612 permit signs allowance off-chain. Relayers or routers submit permit + action atomically. Requires ERC20Permit on the token. See the dedicated article for signature domains, nonces, and ERC-4337 comparison.
- Deadline parameter bounds signature lifetime.
- Integrators must use the correct spender address in the signed struct.
- Failed permit often means wrong nonce or expired deadline — not always 'scam'.
Contract-side patterns
Pull over push: have users approve then transferFrom into your contract rather than pushing tokens to arbitrary addresses. Use ReentrancyGuard on functions that transfer out after state updates. Pausable can stop deposits if an exploit is suspected.
- forceApprove (OZ) helps tokens with non-standard approve behavior.
- SafeERC20 wraps calls that return no bool on legacy tokens.
- Document required approvals in your frontend before users hit errors.
