sourcekeeper_42-contract-lab/contracts/LabContract.sol

122 lines
3.6 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./interfaces/ILabRegistry.sol";
import "./LabHelper.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
contract LabContract is Ownable, ReentrancyGuard {
ILabRegistry public labRegistry;
LabHelper public labHelper;
struct ExperimentConfig {
address creator;
uint256 startTimestamp;
uint256 fundingAmount;
bool isActive;
bytes32 configHash;
}
mapping(bytes32 => ExperimentConfig) public experiments;
mapping(address => bytes32[]) public creatorExperiments;
event ExperimentCreated(
bytes32 indexed experimentId,
address indexed creator,
uint256 fundingAmount
);
event ExperimentUpdated(
bytes32 indexed experimentId,
bool isActive
);
constructor(address _registryAddress, address _helperAddress) {
require(_registryAddress != address(0), "Invalid registry address");
require(_helperAddress != address(0), "Invalid helper address");
labRegistry = ILabRegistry(_registryAddress);
labHelper = LabHelper(_helperAddress);
}
function createExperiment(
uint256 fundingAmount,
bytes32 configHash
) external nonReentrant {
require(fundingAmount > 0, "Funding must be greater than zero");
require(configHash != bytes32(0), "Invalid config hash");
bytes32 experimentId = keccak256(
abi.encodePacked(msg.sender, block.timestamp, configHash)
);
ExperimentConfig memory newExperiment = ExperimentConfig({
creator: msg.sender,
startTimestamp: block.timestamp,
fundingAmount: fundingAmount,
isActive: true,
configHash: configHash
});
experiments[experimentId] = newExperiment;
creatorExperiments[msg.sender].push(experimentId);
require(
labRegistry.registerExperiment(experimentId, msg.sender),
"Experiment registration failed"
);
emit ExperimentCreated(experimentId, msg.sender, fundingAmount);
}
function updateExperimentStatus(
bytes32 experimentId,
bool newStatus
) external nonReentrant {
ExperimentConfig storage experiment = experiments[experimentId];
require(
experiment.creator == msg.sender,
"Only experiment creator can update status"
);
experiment.isActive = newStatus;
emit ExperimentUpdated(experimentId, newStatus);
}
function getExperimentDetails(
bytes32 experimentId
) external view returns (ExperimentConfig memory) {
ExperimentConfig memory experiment = experiments[experimentId];
require(
experiment.creator != address(0),
"Experiment does not exist"
);
return experiment;
}
function withdrawFunds(
bytes32 experimentId,
uint256 amount
) external nonReentrant {
ExperimentConfig storage experiment = experiments[experimentId];
require(
experiment.creator == msg.sender,
"Only experiment creator can withdraw"
);
require(experiment.fundingAmount >= amount, "Insufficient funds");
require(experiment.isActive, "Experiment is not active");
experiment.fundingAmount -= amount;
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success, "Transfer failed");
}
receive() external payable {}
}