External calls

From WEB3 Vulnerapedia
Jump to navigation Jump to search

External calls reentrancy can be executed by the availability of an external call to an attacker controlled contract. External calls allow for the callee to execute arbitrary code. The existence of an external call may not always be obvious, so it's important to be aware of any way in which an external call may be executed in your smart contracts.

ETH transfers

When Ether is transferred to a contract address, it will trigger the receive or fallback function, as implemented in the contract. An attacker can write any arbitrary logic into the fallback method, such that anytime the contract receives a transfer, that logic is executed.

safeMint

One example of a hard to spot external call is OpenZeppelin's ERC721._safeMint & ERC721._safeTransfer functions.

/**
   * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
   * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
   */
 function _safeMint(
     address to,
     uint256 tokenId,
     bytes memory _data
 ) internal virtual {
     _mint(to, tokenId);
     require(
         _checkOnERC721Received(address(0), to, tokenId, _data),
         "ERC721: transfer to non ERC721Receiver implementer"
     );
 }

The function is titled _safeMint because it prevents tokens from being unintentionally minted to a smart contract by checking first whether that contract has implemented ERC721Receiver, i.e. marking itself as a willing recipient of NFTs. This all seems fine, but _checkOnERC721Received is an external call to the receiving contract, allowing arbitrary execution.

Source

https://github.com/kadenzipfel/smart-contract-vulnerabilities/blob/master/vulnerabilities/reentrancy.md