FulfillInterpreter - Missing check whether callTo address contains code
Resolution\\nThis issue has been fixed.\\nThe receiver-side `prepare` checks whether the `callTo` address is either zero or a contract:\\n```\\n// Check that the callTo is a contract\\n// NOTE: This cannot happen on the sending chain (different chain\\n// contexts), so a user could mistakenly create a transfer that must be\\n// cancelled if this is incorrect\\nrequire(invariantData.callTo == address(0) || Address.isContract(invariantData.callTo), "#P:031");\\n```\\n\\nHowever, as a contract may `selfdestruct` and the check is not repeated later, there is no guarantee that `callTo` still contains code when the call to this address (assuming it is non-zero) is actually executed in FulfillInterpreter.execute:\\n```\\n// Try to execute the callData\\n// the low level call will return `false` if its execution reverts\\n(bool success, bytes memory returnData) = callTo.call{value: isEther ? amount : 0}(callData);\\n\\nif (!success) {\\n  // If it fails, transfer to fallback\\n  Asset.transferAsset(assetId, fallbackAddress, amount);\\n  // Decrease allowance\\n  if (!isEther) {\\n    Asset.decreaseERC20Allowance(assetId, callTo, amount);\\n  }\\n}\\n```\\n\\nAs a result, if the contract at `callTo` self-destructs between `prepare` and `fulfill` (both on the receiving chain), `success` will be `true`, and the funds will probably be lost to the user.\\nA user could currently try to avoid this by checking that the contract still exists before calling `fulfill` on the receiving chain, but even then, they might get front-run by `selfdestruct`, and the situation is even worse with a relayer, so this provides no reliable protection.
Repeat the `Address.isContract` check on `callTo` before making the external call in `FulfillInterpreter.execute` and send the funds to the `fallbackAddress` if the result is `false`.\\nIt is, perhaps, debatable whether the check in `prepare` should be kept or removed. In principle, if the contract gets deployed between `prepare` and `fulfill`, that is still soon enough. However, if the `callTo` address doesn't have code at the time of `prepare`, this seems more likely to be a mistake than a “late deployment”. So unless there is a demonstrated use case for “late deployments”, failing in `prepare` (even though it's receiver-side) might still be the better choice.\\nRemark\\nIt should be noted that an unsuccessful call, i.e., a revert, is the only behavior that is recognized by `FulfillInterpreter.execute` as failure. While it is prevalent to indicate failure by reverting, this doesn't have to be the case; a well-known example is an ERC20 token that indicates a failing transfer by returning `false`.\\nA user who wants to utilize this feature has to make sure that the called contract behaves accordingly; if that is not the case, an intermediary contract may be employed, which, for example, reverts for return value `false`.
```\\n// Check that the callTo is a contract\\n// NOTE: This cannot happen on the sending chain (different chain\\n// contexts), so a user could mistakenly create a transfer that must be\\n// cancelled if this is incorrect\\nrequire(invariantData.callTo == address(0) || Address.isContract(invariantData.callTo), "#P:031");\\n```\\n