I have 2 contracts: PolicyFactory (a contract that constructs Policy contracts) and Policy.
In my React app any user can apply for a policy (i have a descentralized life insurance app), resulting in the creation of a Policy contract for each policy.
I want to implement a logic that close the policy and send the funds to the owner automatically when the end date of the policy is due (i store the end date as uint256 in the smart contract).
I tried this with Chainlink Keeper but i found it impossible since i need a keeper for every new Policy contract that is created...
How can i automate this for every policy my users have?
These are my contracts:
import "https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.7/KeeperCompatible.sol";
contract PolicyFactory {
//address[] public deployedPolicies;
mapping(address => address[]) private deployedPoliciesByUser;
address[] private deployedPolicies;
address private admin = 0x3402c11c6f40e28b1D3996f11E5e54a937161fb9;
event PolicyCreation(address policyAddress, string applicationId);
modifier restricted(){
require(msg.sender == admin, 'Not admin!');
_;
}
function createPolicy(uint timePeriod, uint premium, address owner, uint startDate, string memory applicationId, uint endDate) public restricted returns (address){
Policy newPolicy = new Policy(owner, premium, timePeriod, startDate, applicationId, endDate);
deployedPoliciesByUser[owner].push(address(newPolicy));
deployedPolicies.push(address(newPolicy));
emit PolicyCreation(address(newPolicy), applicationId);
}
function getDeployedPoliciesByUser(address user) public view returns (address[] memory) {
require(user != address(0));
return deployedPoliciesByUser[user];
}
function getDeployedPolicies() public view restricted returns (address[] memory) {
return deployedPolicies;
}
}
contract Policy is KeeperCompatibleInterface {
address public owner;
address public admin = 0x3402c11c6f40e28b1D3996f11E5e54a937161fb9;
string public applicationId;
uint public timePeriod;
uint public premium;
uint public startDate;
uint public endDate;
uint public nrPremiumsPayed;
bool public active = true;
event LogDeposit(address _from, uint amount, uint date);
event LogWithdraw(address _to, uint amount, uint date);
modifier restrictedAdminAndOwner(){
require(address(msg.sender) == admin || address(msg.sender) == owner);
_;
}
constructor(address _owner, uint _premium, uint _period, uint _startDate, string memory _applicationId, uint _endDate) public {
owner = _owner;
timePeriod = _period;
premium = _premium;
startDate = _startDate;
endDate = _endDate;
applicationId = _applicationId;
}
function checkUpkeep(bytes calldata /* checkData */) external view override returns (bool upkeepNeeded, bytes memory /* performData */) {
upkeepNeeded = (endDate - block.timestamp) <= 100000;
}
function performUpkeep(bytes calldata /* performData */) external override {
if((endDate - block.timestamp) <= 100000) {
active = false;
(bool sent, ) = address(owner).call{value: address(this).balance}("");
require(sent);
}
}
// de intregrat cu oracle de ipfs sa trimita automat cand se gaseste document.
function sendCompensation () public restrictedAdminAndOwner {
require(owner != address(0) && active == false);
(bool sent, ) = address(owner).call{value: address(this).balance}("");
require(sent);
}
function getSummary () public view returns(address, address, uint, uint, uint, bool, uint, uint){
return (
owner, admin, timePeriod,premium,startDate,active,address(this).balance, endDate
);
}
function withdraw (uint amount, bool closePolicy) public {
require(msg.sender == owner && amount <= address(this).balance && active == true);
(bool sent, ) = address(owner).call{value: amount}("");
require(sent);
if(closePolicy == true){
active = false;
sendCompensation();
}
emit LogWithdraw(address(owner), amount, block.timestamp);
}
function deposit () public payable {
require(active == true);
emit LogDeposit(address(msg.sender), msg.value, block.timestamp);
}
}
Let the contract execute automatically on blockchain is impossible, but there are some alternative solution.
Some simple ideas
You can use ethers.js or web3.js libary to interact with blockchain. But be aware, if you want to change any data on blockchain. You will spend a certain amount of gas fee(like automatically send the funds to the owner).
You can create a dapp ,when the time up, the dapp will show people that they can claim there own fund.(Because the executer is people who claim.)
If I have any new idea I will update ASAF. :)