diff --git a/contracts/dex/DODOAtomicSeeder.sol b/contracts/dex/DODOAtomicSeeder.sol new file mode 100644 index 0000000..53c8c0c --- /dev/null +++ b/contracts/dex/DODOAtomicSeeder.sol @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +interface IERC20AtomicSeeder { + function transferFrom(address from, address to, uint256 amount) external returns (bool); +} + +interface IDODOAtomicSeedPool { + function buyShares(address to) external returns (uint256 baseShare, uint256 quoteShare, uint256 lpShare); +} + +/** + * @title DODOAtomicSeeder + * @notice Pulls both DODO DVM seed tokens and mints LP shares in one transaction. + * @dev This avoids exposing half-seeded pools between separate ERC-20 transfers. + */ +contract DODOAtomicSeeder { + error TransferFromFailed(address token); + error ZeroAddress(); + + function seed( + address pool, + address baseToken, + address quoteToken, + uint256 baseAmount, + uint256 quoteAmount, + address recipient + ) external returns (uint256 baseShare, uint256 quoteShare, uint256 lpShare) { + if (pool == address(0) || baseToken == address(0) || quoteToken == address(0) || recipient == address(0)) { + revert ZeroAddress(); + } + + _safeTransferFrom(baseToken, msg.sender, pool, baseAmount); + _safeTransferFrom(quoteToken, msg.sender, pool, quoteAmount); + return IDODOAtomicSeedPool(pool).buyShares(recipient); + } + + function _safeTransferFrom(address token, address from, address to, uint256 amount) internal { + if (amount == 0) return; + (bool ok, bytes memory data) = token.call( + abi.encodeWithSelector(IERC20AtomicSeeder.transferFrom.selector, from, to, amount) + ); + if (!ok || (data.length != 0 && !abi.decode(data, (bool)))) { + revert TransferFromFailed(token); + } + } +}