Untitled
unknown
plain_text
a year ago
5.8 kB
10
Indexable
// Interface for distribution strategies interface IDistributionStrategy { function distribute() external; } // MasterVault Contract contract MasterVault is AccessControl { IERC20 public ubxToken; bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); struct Subvault { address vaultAddress; uint256 allocation; } Subvault[] public subvaults; uint256 public totalAllocations; event SubvaultRegistered(address indexed vaultAddress, uint256 allocation); event TokensDistributed(address indexed vaultAddress, uint256 amount); constructor(IERC20 _ubxToken) { ubxToken = _ubxToken; _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(ADMIN_ROLE, msg.sender); } function registerSubvault(address vaultAddress, uint256 allocation) external onlyRole(ADMIN_ROLE) { require(vaultAddress != address(0), "Invalid vault address"); require(allocation > 0, "Allocation must be greater than zero"); for (uint256 i = 0; i < subvaults.length; i++) { require(subvaults[i].vaultAddress != vaultAddress, "Vault already registered"); } subvaults.push(Subvault(vaultAddress, allocation)); totalAllocations += allocation; emit SubvaultRegistered(vaultAddress, allocation); } function distributeTokens(uint256 amount) external onlyRole(ADMIN_ROLE) { require(totalAllocations > 0, "No subvaults registered"); for (uint256 i = 0; i < subvaults.length; i++) { Subvault storage subvault = subvaults[i]; uint256 distributeAmount = (amount * subvault.allocation) / totalAllocations; require(ubxToken.transfer(subvault.vaultAddress, distributeAmount), "Transfer failed"); IDistributionStrategy(subvault.vaultAddress).distribute(); emit TokensDistributed(subvault.vaultAddress, distributeAmount); } } } // PrivateSaleVault Contract contract PrivateSaleVault is IDistributionStrategy, AccessControl { IERC20 public ubxToken; uint256 public totalAllocation; uint256 public initialReleaseAmount; uint256 public vestingStartTime; uint256 public vestingDuration; uint256 public withdrawInterval; uint256 public totalParticipantAllocation; struct Participant { uint256 allocation; uint256 withdrawn; uint256 lastWithdrawTime; } mapping(address => Participant) private participants; bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE"); event TokensWithdrawn(address indexed user, uint256 amount); event ParticipantAdded(address indexed participant, uint256 allocation); event ParticipantRemoved(address indexed participant); constructor( IERC20 _ubxToken, uint256 _totalAllocation, uint256 _vestingStartTime, uint256 _vestingDuration, uint256 _withdrawInterval ) { ubxToken = _ubxToken; totalAllocation = _totalAllocation; initialReleaseAmount = (_totalAllocation * 10) / 100; // 10% initial release vestingStartTime = _vestingStartTime; vestingDuration = _vestingDuration; withdrawInterval = _withdrawInterval; _setupRole(DEFAULT_ADMIN_ROLE, msg.sender); _setupRole(ADMIN_ROLE, msg.sender); } function addParticipant(address participant, uint256 allocation) external onlyRole(ADMIN_ROLE) { require(participant != address(0), "Invalid participant address"); require(allocation > 0, "Invalid allocation"); require(participants[participant].allocation == 0, "Participant already added"); participants[participant] = Participant({ allocation: allocation, withdrawn: 0, lastWithdrawTime: vestingStartTime }); totalParticipantAllocation += allocation; emit ParticipantAdded(participant, allocation); } function removeParticipant(address participant) external onlyRole(ADMIN_ROLE) { require(participant != address(0), "Invalid participant address"); require(participants[participant].allocation > 0, "Participant not found"); totalParticipantAllocation -= participants[participant].allocation; delete participants[participant]; emit ParticipantRemoved(participant); } function calculateVestedAmount(address participant) public view returns (uint256) { if (block.timestamp < vestingStartTime) { return 0; } uint256 initialAmount = (participants[participant].allocation * 10) / 100; uint256 elapsedTime = block.timestamp - vestingStartTime; uint256 totalVested = initialAmount + ((participants[participant].allocation * 90 * elapsedTime) / (100 * vestingDuration)); uint256 participantShare = (totalVested * participants[participant].allocation) / totalParticipantAllocation; return participantShare; } function withdrawTokens() external { require(block.timestamp >= vestingStartTime, "Vesting period not started"); require(block.timestamp >= participants[msg.sender].lastWithdrawTime + withdrawInterval, "Withdraw interval not reached"); uint256 vestedAmount = calculateVestedAmount(msg.sender); uint256 withdrawableAmount = vestedAmount - participants[msg.sender].withdrawn; require(withdrawableAmount > 0, "No tokens available for withdrawal"); participants[msg.sender].withdrawn += withdrawableAmount; participants[msg.sender].lastWithdrawTime = block.timestamp; require(ubxToken.transfer(msg.sender, withdrawableAmount), "Transfer failed"); emit TokensWithdrawn(msg.sender, withdrawableAmount); } }
Editor is loading...
Leave a Comment