Skip to content

Instantly share code, notes, and snippets.

@beauwilliams
Created March 12, 2022 00:00
Show Gist options
  • Save beauwilliams/bfcf864bc539d368e23758c6ead52261 to your computer and use it in GitHub Desktop.
Save beauwilliams/bfcf864bc539d368e23758c6ead52261 to your computer and use it in GitHub Desktop.
A demonstraction of a claimable allocation contract for MACS
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.0;
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
interface IERC20 {
function totalSupply() external view returns (uint256);
function decimals() external view returns (uint8);
function symbol() external view returns (string memory);
function name() external view returns (string memory);
function getOwner() external view returns (address);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address _owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
abstract contract Auth {
address owner;
mapping (address => bool) private authorisations;
constructor(address _owner) {
owner = _owner;
authorisations[_owner] = true;
}
modifier onlyOwner() {
require(isOwner(msg.sender)); _;
}
modifier authorised() {
require(isAuthorised(msg.sender)); _;
}
function authorise(address adr) public onlyOwner {
authorisations[adr] = true;
emit Authorised(adr);
}
function unauthorise(address adr) public onlyOwner {
authorisations[adr] = false;
emit Unauthorised(adr);
}
function isOwner(address account) public view returns (bool) {
return account == owner;
}
function isAuthorised(address adr) public view returns (bool) {
return authorisations[adr];
}
function transferOwnership(address newOwner) public onlyOwner {
address oldOwner = owner;
owner = newOwner;
authorisations[oldOwner] = false;
authorisations[newOwner] = true;
emit Unauthorised(oldOwner);
emit OwnershipTransferred(oldOwner, newOwner);
}
event OwnershipTransferred(address oldOwner, address newOwner);
event Authorised(address adr);
event Unauthorised(address adr);
}
contract MACSAllocation is Auth {
using SafeMath for uint256;
address public MACSTokenAddress;
bool public allocated;
mapping (address => uint256) public shares;
mapping (address => bool) public claimed;
uint256 public totalShares;
uint256 public totalClaimed;
constructor(address _MACSTokenAddress) Auth(msg.sender) {
MACSTokenAddress = _MACSTokenAddress;
allocated = false;
}
modifier allocate(){
require(!allocated);
_;
allocated = true;
}
modifier canClaim(){
require(allocated); _;
}
function createAllocation(address[] memory holders, uint256[] memory amounts) external authorised allocate {
for(uint256 i; i<holders.length; i++){
shares[holders[i]] = amounts[i];
totalShares += amounts[i];
}
}
function getClaimableShares(address holder) public view returns (uint256) {
if (!allocated) return 0;
if (claimed[msg.sender]) return 0;
return shares[holder];
}
function getPendingAmount(address holder) public view returns (uint256) {
if(!allocated) return 0;
if (claimed[msg.sender]) return 0;
uint256 claimableShares = getClaimableShares(holder);
uint256 remainingTotalShares = totalShares - totalClaimed;
return claimableShares * getAllocatedTokenBalance() / remainingTotalShares;
}
function claim() external canClaim {
uint256 amount = getPendingAmount(msg.sender);
if(amount > 0){
uint256 claiming = getClaimableShares(msg.sender);
claimed[msg.sender] = true;
totalClaimed += claiming;
IERC20(MACSTokenAddress).transfer(msg.sender, amount);
}
}
function updateTokenAddress(address newTokenAddr) public authorised {
MACSTokenAddress = newTokenAddr;
}
function getAllocatedTokenBalance() public view returns (uint256) {
return IERC20(MACSTokenAddress).balanceOf(address(this));
}
function withdrawTokensToBeneficiary(address beneficiary) public authorised {
require(IERC20(MACSTokenAddress).transfer(beneficiary, IERC20(MACSTokenAddress).balanceOf(address(this))));
}
function withdrawTokens() external authorised {
require(IERC20(MACSTokenAddress).transfer(msg.sender, IERC20(MACSTokenAddress).balanceOf(address(this))));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment