// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; /** * @title AtomicSettlementHub * @notice تنفيذ صفقة ذرية لنقل توكن (stablecoin) من buyer إلى seller وتسجيل الصفقة. * - Uses SafeERC20 to support tokens that don't return bool. * - Uses ReentrancyGuard and Checks-Effects-Interactions pattern. / contract AtomicSettlementHub is ReentrancyGuard, Ownable { using SafeERC20 for IERC20; struct Deal { address buyer; address seller; uint256 price; bool isSettled; uint256 timestamp; } mapping(bytes32 => Deal) public deals; IERC20 public immutable token; event AtomicSettlementSuccess( bytes32 indexed dealId, address indexed buyer, address indexed seller, uint256 price, uint256 timestamp ); event EmergencyWithdraw(address indexed to, uint256 amount); constructor(address _tokenAddress) { require(_tokenAddress != address(0), "token address zero"); token = IERC20(_tokenAddress); } /* * @notice Execute an atomic settlement. Buyer must approve this contract for _price. * @dev Checks-Effects-Interactions + nonReentrant / function executeAtomicSettlement( bytes32 _dealId, address _seller, uint256 _price ) external nonReentrant { address buyer = msg.sender; require(_seller != address(0), "seller zero address"); require(_price > 0, "price must be > 0"); require(buyer != _seller, "buyer and seller must differ"); require(!deals[_dealId].isSettled, "deal already settled"); // Effects: record the deal first to prevent double-spend/reentrancy attempts deals[_dealId] = Deal({ buyer: buyer, seller: _seller, price: _price, isSettled: true, timestamp: block.timestamp }); // Interaction: transfer tokens safely token.safeTransferFrom(buyer, _seller, _price); emit AtomicSettlementSuccess(_dealId, buyer, _seller, _price, block.timestamp); } /* * @notice Emergency: owner can withdraw tokens accidentally sent to this contract. * @dev Only owner, for recovery purposes. / function emergencyWithdraw(address _to, uint256 _amount) external onlyOwner { require(_to != address(0), "to zero"); token.safeTransfer(_to, _amount); emit EmergencyWithdraw(_to, _amount); } /* * @notice Get deal info */ function getDeal(bytes32 _dealId) external view returns (Deal memory) { return deals[_dealId]; } }# -
ramdan09a-bot/-
Folders and files
| Name | Name | Last commit date | ||
|---|---|---|---|---|