Skip to content

Commit

Permalink
Merge pull request #629 from morpho-org/fix/issue-5
Browse files Browse the repository at this point in the history
fix(safe-transfer-lib): check for code
  • Loading branch information
MerlinEgalite committed Dec 5, 2023
2 parents e4ccec8 + d40529a commit 9346293
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 3 deletions.
3 changes: 3 additions & 0 deletions src/libraries/ErrorsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ library ErrorsLib {
/// @notice Thrown when the market is already created.
string internal constant MARKET_ALREADY_CREATED = "market already created";

/// @notice Thrown when a token to transfer doesn't have code.
string internal constant NO_CODE = "no code";

/// @notice Thrown when the market is not created.
string internal constant MARKET_NOT_CREATED = "market not created";

Expand Down
7 changes: 4 additions & 3 deletions src/libraries/SafeTransferLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,19 @@ interface IERC20Internal {
/// @custom:contact security@morpho.org
/// @notice Library to manage transfers of tokens, even if calls to the transfer or transferFrom functions are not
/// returning a boolean.
/// @dev It is the responsibility of the market creator to make sure that the address of the token has non-zero code.
library SafeTransferLib {
/// @dev Warning: It does not revert on `token` with no code.
function safeTransfer(IERC20 token, address to, uint256 value) internal {
require(address(token).code.length > 0, ErrorsLib.NO_CODE);

(bool success, bytes memory returndata) =
address(token).call(abi.encodeCall(IERC20Internal.transfer, (to, value)));
require(success, ErrorsLib.TRANSFER_REVERTED);
require(returndata.length == 0 || abi.decode(returndata, (bool)), ErrorsLib.TRANSFER_RETURNED_FALSE);
}

/// @dev Warning: It does not revert on `token` with no code.
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
require(address(token).code.length > 0, ErrorsLib.NO_CODE);

(bool success, bytes memory returndata) =
address(token).call(abi.encodeCall(IERC20Internal.transferFrom, (from, to, value)));
require(success, ErrorsLib.TRANSFER_FROM_REVERTED);
Expand Down
12 changes: 12 additions & 0 deletions test/forge/integration/SupplyCollateralIntegrationTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ contract SupplyCollateralIntegrationTest is BaseTest {
morpho.supplyCollateral(marketParams, amount, address(0), hex"");
}

function testSupplyCollateralTokenNotCreated(uint256 amount, address token) public {
amount = bound(amount, 1, MAX_TEST_AMOUNT);

vm.assume(token.code.length == 0);

marketParams.collateralToken = token;
morpho.createMarket(marketParams);

vm.expectRevert(bytes(ErrorsLib.NO_CODE));
morpho.supplyCollateral(marketParams, amount, ONBEHALF, hex"");
}

function testSupplyCollateral(uint256 amount) public {
amount = bound(amount, 1, MAX_COLLATERAL_ASSETS);

Expand Down
12 changes: 12 additions & 0 deletions test/forge/integration/SupplyIntegrationTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ contract SupplyIntegrationTest is BaseTest {
morpho.supply(marketParams, amount, shares, address(0), hex"");
}

function testSupplyTokenNotCreated(uint256 amount, address token) public {
amount = bound(amount, 1, MAX_TEST_AMOUNT);

vm.assume(token.code.length == 0);

marketParams.loanToken = token;
morpho.createMarket(marketParams);

vm.expectRevert(bytes(ErrorsLib.NO_CODE));
morpho.supply(marketParams, amount, 0, ONBEHALF, hex"");
}

function testSupplyAssets(uint256 amount) public {
amount = bound(amount, 1, MAX_TEST_AMOUNT);

Expand Down
14 changes: 14 additions & 0 deletions test/forge/libraries/SafeTransferLibTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,20 @@ contract SafeTransferLibTest is Test {
this.safeTransferFrom(address(tokenWithBooleanAlwaysFalse), from, to, amount);
}

function testSafeTransferTokenNotCreated(address token, address to, uint256 amount) public {
vm.assume(token.code.length == 0);

vm.expectRevert(bytes(ErrorsLib.NO_CODE));
this.safeTransfer(token, to, amount);
}

function testSafeTransferFromTokenNotCreated(address token, address from, address to, uint256 amount) public {
vm.assume(token.code.length == 0);

vm.expectRevert(bytes(ErrorsLib.NO_CODE));
this.safeTransferFrom(token, from, to, amount);
}

function safeTransfer(address token, address to, uint256 amount) external {
IERC20(token).safeTransfer(to, amount);
}
Expand Down

0 comments on commit 9346293

Please sign in to comment.