Solidity gotchas
A contract has these modifiers and a function:
contract X {
bool public paused = true;
address public owner;
modifier whenNotPaused() {
require(!paused, "paused");
_;
}
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}
function adminAction() external whenNotPaused onlyOwner {
// body
}
}
A non-owner calls `adminAction()` while the contract is paused. What is the revert message?
A contract has this function:
function trySend(address payable to, uint256 amount) external {
(bool ok, ) = to.call{value: amount}("");
// no further code
}The to address is a contract whose receive() always reverts. A user calls trySend with amount = 1 ether. What happens?
A developer writes this modifier to track call counts and applies it to several functions
uint256 public callCount;
modifier counted() {
callCount += 1;
}
function doStuff() external counted {
// important logic here
}The contract deploys without errors. What happens when a user calls doStuff()?
A vault contract reverts all direct ETH transfers via receive
contract Vault {
uint256 public trackedBalance;
function deposit() external payable {
trackedBalance += msg.value;
}
receive() external payable {
revert("use deposit()");
}
}An attacker creates a separate contract, sends 5 ETH to it, then calls selfdestruct on it with the Vault's address as the recipient. What is the state of the Vault afterwards?
Approve without sufficient balance Alice has a balance of 50 USDC. She calls usdc.approve(bob, 1000). What is the result?
A protocol integrates a new token and uses this code
function notify(address token, address user) external {
(bool ok, ) = token.call(
abi.encodeWithSignature("notifyDeposit(address)", user)
);
require(ok, "notify failed");
}The token address is set by an admin. Through misconfiguration, the admin sets token to an address that has no contract deployed. What happens when notify is called?