Maak een Solidity Smart Contract voor Geautomatiseerde Dividenduitkering
description
Deze prompt helpt gebruikers een praktische en geautomatiseerde oplossing te creëren voor winstverdeling in getokeniseerde projecten, wat tijd bespaart en fouten bij handmatige distributie vermindert. Het richt zich op veiligheid en efficiëntie, wat het beter maakt dan handmatige dividend systemen of generieke contracten.
prompt
try_prompt
Help me een Solidity smart contract te ontwikkelen voor geautomatiseerde dividenduitkering. Het contract moet functies bevatten zoals het bijhouden van aandeelhoudersbalansen: <voer de lijst of methode voor bijhouden in>, het berekenen van dividenden ... more
generate_helper
...
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Hier is een voorbeeld van een Solidity smart contract voor geautomatiseerde dividenduitkering, met aandacht voor veiligheid, efficiëntie en functionaliteit:
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract DividendUitkering {
// Aandeelhoudersbalansen
mapping(address => uint256) public balansen;
// Lijst van aandeelhouders voor iteratie
address[] publiekeAandeelhouders;
// Totale aandelen
uint256 public totaalAandelen;
// Dividendbeheer
uint256 public dividendPerAandeel;
uint256 public laatsteUitkeringTijd;
uint256 public uitkeringsInterval = 30 days; // Maandelijks
// Operator of beheerder
address public beheerder;
// Events
event AandeelToegevoegd(address aandeelhouder, uint256 hoeveelheid);
event AandeelVerwijderd(address aandeelhouder);
event DividendUitbetaald(uint256 bedrag, uint256 tijdstip);
event DividendBerekenen(uint256 bedragPerAandeel);
modifier onlyBeheerder() {
require(msg.sender == beheerder, "Alleen beheerder toegestaan");
_;
}
constructor() {
beheerder = msg.sender;
laatsteUitkeringTijd = block.timestamp;
}
// Aandeel toevoegen
function voegAandeelToe(address aandeelhouder, uint256 hoeveelheid) external onlyBeheerder {
require(aandeelhouder != address(0), "Ongeldig adres");
if (balansen[aandeelhouder] == 0) {
publiekeAandeelhouders.push(aandeelhouder);
}
balansen[aandeelhouder] += hoeveelheid;
totaalAandelen += hoeveelheid;
emit AandeelToegevoegd(aandeelhouder, hoeveelheid);
}
// Aandeel verwijderen
function verwijderAandeel(address aandeelhouder, uint256 hoeveelheid) external onlyBeheerder {
require(balansen[aandeelhouder] >= hoeveelheid, "Onvoldoende saldo");
balansen[aandeelhouder] -= hoeveelheid;
totaalAandelen -= hoeveelheid;
if (balansen[aandeelhouder] == 0) {
// Optioneel: verwijder uit lijst
// Voor eenvoud niet volledig geïmplementeerd
}
emit AandeelVerwijderd(aandeelhouder);
}
// Dividend berekenen en plannen
function berekenDividend() public onlyBeheerder {
require(block.timestamp >= laatsteUitkeringTijd + uitkeringsInterval, "Nog niet tijd voor uitkering");
uint256 contractBalans = address(this).balance;
require(totaalAandelen > 0, "Geen aandelen");
// Dividend per aandeel
dividendPerAandeel = contractBalans / totaalAandelen;
laatsteUitkeringTijd = block.timestamp;
emit DividendBerekenen(dividendPerAandeel);
}
// Aandeelhouder claimen
mapping(address => bool) public heeftGeclaimd;
function claimDividend() external {
require(balansen[msg.sender] > 0, "Geen aandelen");
require(block.timestamp >= laatsteUitkeringTijd, "Uitkering nog niet gestart");
require(!heeftGeclaimd[msg.sender], "Dividend al geclaimd");
uint256 teBetalen = balansen[msg.sender] * dividendPerAandeel;
require(teBetalen > 0, "Geen dividend om te claimen");
heeftGeclaimd[msg.sender] = true;
(bool success, ) = msg.sender.call{value: teBetalen}("");
require(success, "Betaling mislukt");
}
// Ontvangst van ETH
receive() external payable {}
// Reset claims voor nieuwe uitkering
function resetClaims() external onlyBeheerder {
for (uint256 i = 0; i < publiekeAandeelhouders.length; i++) {
heeftGeclaimd[publiekeAandeelhouders[i]] = false;
}
}
}
```
**Belangrijke punten:**
- **Veiligheid:** Gebruik van `call` voor ETH-overdracht met controle op success, checks-effecten-cascade patroon niet volledig nodig hier, maar belangrijk bij meer complexe contracten.
- **Gaskosten:** Lijst van aandeelhouders wordt niet dynamisch verwijderd; voor grote groepen moet een andere aanpak worden overwogen. Alternatief is gebruik van off-chain logs en claimproces.
- **Dividendplan:** Dividend wordt maandelijks berekend, afhankelijk van de ETH in het contract.
- **Claimproces:** Aandeelhouders kunnen hun dividend claimen; claims worden gereset na elke dividendperiode.
**Aanpassingen en uitbreidingen:**
- Voeg functies toe voor automatische planning met Chainlink Keepers of andere scheduler.
- Beheer van aandeelhouders via events en off-chain tracking.
- Verbeterde lijstbeheer voor grote groepen aandeelhouders.
- Mogelijkheid om dividend uit te keren in tokens in plaats van ETH.
Heeft u verdere wensen of specifieke functionaliteiten?
provider: deepseek
model: deepseek-chat
Zeker, hier is een veilig en gas-efficiënt Solidity smart contract voor geautomatiseerde dividenduitkering met uitleg:
```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract DividendDistributor is Ownable, ReentrancyGuard {
// Token waarop dividenden worden uitgekeerd
IERC20 public dividendToken;
// Totaal aantal uitstaande tokens
uint256 public totalSupply;
// Aandeelhoudersbalansen
mapping(address => uint256) public balances;
// Dividend tracking variabelen
uint256 public totalDividendDistributed;
uint256 public lastDistributionTime;
uint256 public distributionInterval = 30 days;
// Claim tracking om double-spending te voorkomen
mapping(address => uint256) public lastClaimTime;
mapping(address => uint256) public claimedDividends;
// Evenementen voor transparantie
event DividendDeposited(uint256 amount, uint256 timestamp);
event DividendClaimed(address indexed shareholder, uint256 amount, uint256 timestamp);
event DistributionScheduled(uint256 nextDistributionTime);
constructor(address _dividendToken) {
require(_dividendToken != address(0), "Ongeldig token adres");
dividendToken = IERC20(_dividendToken);
lastDistributionTime = block.timestamp;
}
// Functie om aandeelhoudersbalansen bij te werken (alleen owner)
function updateShareholder(address shareholder, uint256 newBalance) external onlyOwner {
require(shareholder != address(0), "Ongeldig aandeelhouder adres");
// Update total supply
totalSupply = totalSupply - balances[shareholder] + newBalance;
balances[shareholder] = newBalance;
}
// Deposit dividend fondsen (alleen owner)
function depositDividends(uint256 amount) external onlyOwner {
require(amount > 0, "Bedrag moet groter zijn dan 0");
require(dividendToken.transferFrom(msg.sender, address(this), amount), "Transfer mislukt");
totalDividendDistributed += amount;
emit DividendDeposited(amount, block.timestamp);
}
// Automatische maandelijkse distributie (alleen owner)
function distributeDividends() external onlyOwner {
require(block.timestamp >= lastDistributionTime + distributionInterval, "Nog niet tijd voor distributie");
require(totalSupply > 0, "Geen tokens in omloop");
// Implementeer hier de automatische distributielogica
// Bijvoorbeeld: bereken en stel dividenden beschikbaar voor claim
lastDistributionTime = block.timestamp;
emit DistributionScheduled(lastDistributionTime + distributionInterval);
}
// Dividend claim functie voor aandeelhouders
function claimDividend() external nonReentrant {
address shareholder = msg.sender;
require(balances[shareholder] > 0, "Geen tokens in bezit");
require(block.timestamp > lastClaimTime[shareholder] + distributionInterval, "Nog niet tijd om te claimen");
uint256 dividendAmount = calculateDividend(shareholder);
require(dividendAmount > 0, "Geen dividenden beschikbaar");
require(dividendToken.balanceOf(address(this)) >= dividendAmount, "Onvoldoende fondsen");
lastClaimTime[shareholder] = block.timestamp;
claimedDividends[shareholder] += dividendAmount;
require(dividendToken.transfer(shareholder, dividendAmount), "Transfer mislukt");
emit DividendClaimed(shareholder, dividendAmount, block.timestamp);
}
// Bereken dividend voor een specifieke aandeelhouder
function calculateDividend(address shareholder) public view returns (uint256) {
if (balances[shareholder] == 0 || totalSupply == 0) {
return 0;
}
// Eenvoudige proportionele berekening
uint256 sharePercentage = (balances[shareholder] * 1e18) / totalSupply;
uint256 dividendAmount = (totalDividendDistributed * sharePercentage) / 1e18;
return dividendAmount - claimedDividends[shareholder];
}
// Emergency withdraw functie (alleen owner)
function emergencyWithdraw(address tokenAddress) external onlyOwner {
IERC20 token = IERC20(tokenAddress);
uint256 balance = token.balanceOf(address(this));
require(token.transfer(owner(), balance), "Emergency withdraw mislukt");
}
// Update distributie interval (alleen owner)
function setDistributionInterval(uint256 newInterval) external onlyOwner {
require(newInterval >= 1 days, "Interval te kort");
distributionInterval = newInterval;
}
}
```
## Beveiligingsmaatregelen:
1. **ReentrancyGuard**: Voorkomt herintredingsaanvallen
2. **OnlyOwner modifiers**: Beveiligde toegang tot kritieke functies
3. **NonReentrant modifier**: Voorkomt race conditions bij claims
4. **Input validatie**: Controleert alle gebruikersinputs
5. **Safe math**: Solidty 0.8.x heeft ingebouwde overflow protection
## Gasoptimalisaties:
1. **Efficiente mappings**: Minimaliseert storage operations
2. **View functions**: Voor berekeningen zonder gas kosten
3. **Events**: Voor goedkope logging i.p.v. storage
4. **Batched operations**: Voor bulk updates (niet getoond maar aanbevolen)
## Gebruiksaanwijzing:
1. Deploy contract met dividend token address
2. Gebruik `updateShareholder` om balansen bij te werken
3. Deposit dividenden met `depositDividends`
4. Roep maandelijks `distributeDividends` aan
5. Aandeelhouders kunnen `claimDividend` aanroepen
Let op: Dit is een basisimplementatie. Voor productiegebruik raad ik aan extra audits en testen uit te voeren, en mogelijk een meer geavanceerde dividendberekeningsmethode te implementeren.

