pragma solidity 0.6.8;
// SPDX-License-Identifier: UNLICENCED
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor () internal {
address msgSender = _msgSender();
_owner = msgSender;
emit OwnershipTransferred(address(0), msgSender);
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return _owner;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(_owner == _msgSender(), "Ownable: caller is not the owner");
_;
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing any functionality that is only available to the owner.
*/
// function renounceOwnership() public onlyOwner {
// emit OwnershipTransferred(_owner, address(0));
// _owner = address(0);
// }
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
constructor () internal {
_paused = false;
}
function paused() public view returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!_paused, "Pausable: paused");
_;
}
modifier whenPaused() {
require(_paused, "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
//Restrictions:
//only 2^32 Users
//Maximum of 2^104 / 10^18 Ether investment. Theoretically 20 Trl Ether, practically 100000000000 Ether compiles
//Maximum of (2^104 / 10^18 Ether) investment. Theoretically 20 Trl Ether, practically 100000000000 Ether compiles
contract PrestigeClub is Ownable(), Pausable() {
struct User {
uint104 deposit; //265 bits together
uint104 payout;
uint32 position;
uint8 qualifiedPools;
uint8 downlineBonus;
address referer;
address[] referrals;
uint104 directSum;
uint40 lastPayout;
uint104[5] downlineVolumes;
}
event NewDeposit(address indexed addr, uint104 amount);
event PoolReached(address indexed addr, uint8 pool);
event DownlineBonusStageReached(address indexed adr, uint8 stage);
event Referral(address indexed addr, address indexed referral);
event Payout(address indexed addr, uint104 interest, uint104 direct, uint104 pool, uint104 downline, uint40 dayz);
event Withdraw(address indexed addr, uint104 amount);
mapping (address => User) users;
address[] userList;
uint32 public lastPosition = 0;
uint128 public depositSum = 0;
Pool[8] public pools;
struct Pool {
uint104 minOwnInvestment;
uint8 minDirects;
uint104 minSumDirects;
uint8 payoutQuote; //ppm
uint32 numUsers;
}
PoolState[] public states;
struct PoolState {
uint128 totalDeposits;
uint32 totalUsers;
uint32[8] numUsers;
}
DownlineBonusStage[4] downlineBonuses;
struct DownlineBonusStage {
uint32 minPool;
uint64 payoutQuote; //ppm
}
uint40 public pool_last_draw;
constructor() public {
uint40 timestamp = uint40(block.timestamp);
pool_last_draw = timestamp - (timestamp % payout_interval);
pools[0] = Pool(3 ether, 1, 3 ether, 130, 0);
pools[1] = Pool(15 ether, 3, 5 ether, 130, 0);
pools[2] = Pool(15 ether, 4, 44 ether, 130, 0);
pools[3] = Pool(30 ether, 10, 105 ether, 130, 0);
pools[4] = Pool(45 ether, 15, 280 ether, 130, 0);
pools[5] = Pool(60 ether, 20, 530 ether, 130, 0);
pools[6] = Pool(150 ether, 20, 1470 ether, 80, 0);
pools[7] = Pool(300 ether, 20, 2950 ether, 80, 0);
downlineBonuses[0] = DownlineBonusStage(3, 50);
downlineBonuses[1] = DownlineBonusStage(4, 100);
downlineBonuses[2] = DownlineBonusStage(5, 160);
downlineBonuses[3] = DownlineBonusStage(6, 210);
userList.push(address(0));
}
uint104 private minDeposit = 1 ether;
uint104 private minWithdraw = 1000 wei;
uint40 constant private payout_interval = 1 days;
function recieve() public payable whenNotPaused {
require(users[_msgSender()].deposit >= minDeposit || msg.value >= minDeposit, "Mininum deposit value not reached");
address sender = _msgSender();
uint104 value = (uint104) (msg.value / 20 * 19);
bool userExists = users[sender].position != 0;
triggerCalculation();
// Create a position for new accounts
if(!userExists){
lastPosition++;
users[sender].position = lastPosition;
users[sender].lastPayout = (uint40(block.timestamp) - (uint40(block.timestamp) % payout_interval) + 1);
userList.push(sender);
}
address referer = users[sender].referer; //can put outside because referer is always set since setReferral() gets called before recieve() in recieve(address)
if(referer != address(0)){
updateUpline(sender, referer, value);
}
//Update Payouts
if(userExists){
updatePayout(sender);
}
users[sender].deposit += value;
//Transfer fee
payable(owner()).transfer(msg.value - value);
emit NewDeposit(sender, value);
updateUserPool(sender);
updateDownlineBonusStage(sender);
if(referer != address(0)){
users[referer].directSum += value;
updateUserPool(referer);
updateDownlineBonusStage(referer);
}
depositSum += value;
}
function recieve(address referer) public payable whenNotPaused {
_setReferral(referer);
recieve();
}
uint8 downlineLimit = 30;
function updateUpline(address reciever, address adr, uint104 addition) private {
address current = adr;
uint8 bonusStage = users[reciever].downlineBonus;
while(current != address(0) && downlineLimit > 0){
updatePayout(current);
users[current].downlineVolumes[bonusStage] += addition;
uint8 currentBonus = users[current].downlineBonus;
if(currentBonus > bonusStage){
bonusStage = currentBonus;
}
current = users[current].referer;
downlineLimit--;
}
}
function updatePayout(address adr) private {
uint40 dayz = (uint40(block.timestamp) - users[adr].lastPayout) / (payout_interval);
if(dayz >= 1){
uint104 interestPayout = getInterestPayout(adr);
uint104 poolpayout = getPoolPayout(adr, dayz);
uint104 directsPayout = getDirectsPayout(adr);
uint104 downlineBonusAmount = getDownlinePayout(adr);
uint104 sum = interestPayout + directsPayout + downlineBonusAmount;
sum = (sum * dayz) + poolpayout;
users[adr].payout += sum;
users[adr].lastPayout += (payout_interval * dayz);
emit Payout(adr, interestPayout, directsPayout, poolpayout, downlineBonusAmount, dayz);
}
}
function getInterestPayout(address adr) public view returns (uint104){
//Calculate Base Payouts
uint8 quote;
uint104 deposit = users[adr].deposit;
if(deposit >= 30 ether){
quote = 15;
}else{
quote = 10;
}
return deposit / 10000 * quote;
}
function getPoolPayout(address adr, uint40 dayz) public view returns (uint104){
uint40 length = (uint40)(states.length);
uint104 poolpayout = 0;
if(users[adr].qualifiedPools > 0){
for(uint40 day = length - dayz ; day < length ; day++){
uint32 numUsers = states[day].totalUsers;
uint104 streamline = (uint104) (states[day].totalDeposits / (numUsers) * (numUsers - users[adr].position));
uint104 payout_day = 0; //TODO Merge into poolpayout, only for debugging
uint32 stateNumUsers = 0;
for(uint8 j = 0 ; j < users[adr].qualifiedPools ; j++){
uint104 pool_base = streamline / 1000000 * pools[j].payoutQuote;
stateNumUsers = states[day].numUsers[j];
if(stateNumUsers != 0){
payout_day += pool_base / stateNumUsers;
}
}
poolpayout += payout_day;
}
}
return poolpayout;
}
function getDownlinePayout(address adr) public view returns (uint104){
//Calculate Downline Bonus
uint104 downlinePayout = 0;
uint8 downlineBonus = users[adr].downlineBonus;
if(downlineBonus > 0){
uint64 ownPercentage = downlineBonuses[downlineBonus - 1].payoutQuote;
for(uint8 i = 0 ; i < downlineBonus; i++){
uint64 quote = 0;
if(i > 0){
quote = downlineBonuses[i - 1].payoutQuote;
}else{
quote = 0;
}
uint64 percentage = ownPercentage - quote;
downlinePayout += users[adr].downlineVolumes[i] * percentage / 1000000;
}
if(downlineBonus == 4){
downlinePayout += users[adr].downlineVolumes[downlineBonus] * 50 / 1000000;
}
}
return downlinePayout;
}
function getDirectsPayout(address adr) public view returns ( uint104) {
//Calculate Directs Payouts
uint104 directsDepositSum = users[adr].directSum;
uint104 directsPayout = directsDepositSum / 10000 * 5;
return (directsPayout);
}
function pushPoolState() private {
uint32[8] memory temp;
for(uint8 i = 0 ; i < 8 ; i++){
temp[i] = pools[i].numUsers;
}
states.push(PoolState(depositSum, lastPosition, temp));
pool_last_draw += payout_interval;
}
function updateUserPool(address adr) private {
if(users[adr].qualifiedPools < pools.length){
uint8 poolnum = users[adr].qualifiedPools;
uint104 sumDirects = users[adr].directSum;
//Check if requirements for next pool are met
if(users[adr].deposit >= pools[poolnum].minOwnInvestment && users[adr].referrals.length >= pools[poolnum].minDirects && sumDirects >= pools[poolnum].minSumDirects){
users[adr].qualifiedPools = poolnum + 1;
pools[poolnum].numUsers++;
emit PoolReached(adr, poolnum + 1);
updateUserPool(adr);
}
}
}
function updateDownlineBonusStage(address adr) private {
uint8 bonusstage = users[adr].downlineBonus;
if(bonusstage < downlineBonuses.length){
//Check if requirements for next stage are met
if(users[adr].qualifiedPools >= downlineBonuses[bonusstage].minPool){
users[adr].downlineBonus += 1;
//Update data in upline
uint104 value = users[adr].deposit; //Value without current stage, since that must not be subtracted
for(uint8 i = 0 ; i <= bonusstage ; i++){
value += users[adr].downlineVolumes[i];
}
uint104 additionValue = value;
uint8 currentBonusStage = bonusstage + 1;
address current = users[adr].referer;
while(current != address(0)){
users[current].downlineVolumes[currentBonusStage - 1] -= value;
users[current].downlineVolumes[currentBonusStage] += additionValue;
current = users[current].referer;
}
emit DownlineBonusStageReached(adr, users[adr].downlineBonus);
updateDownlineBonusStage(adr);
}
}
}
function calculateDirects() external view returns (uint128 sum, uint32 numDirects) {
return calculateDirects(_msgSender());
}
function calculateDirects(address adr) private view returns (uint104, uint32) {
address[] memory referrals = users[adr].referrals;
uint104 sum = 0;
for(uint32 i = 0 ; i < referrals.length ; i++){
sum += users[referrals[i]].deposit;
}
return (sum, (uint32)(referrals.length));
}
//Endpoint to withdraw payouts
function withdraw(uint104 amount) public whenNotPaused {
updatePayout(_msgSender());
require(amount > minWithdraw, "Minimum Withdrawal amount not met");
require(users[_msgSender()].payout >= amount, "Not enough payout available to cover withdrawal request");
uint104 transfer = amount / 20 * 19;
payable(_msgSender()).transfer(transfer);
users[_msgSender()].payout -= amount;
emit Withdraw(_msgSender(), amount);
payable(owner()).transfer(amount - transfer);
}
function _setReferral(address referer) private {
if(users[_msgSender()].referer == referer){
return;
}
if(users[_msgSender()].position != 0 && users[_msgSender()].position < users[referer].position) {
return;
}
require(users[_msgSender()].referer == address(0), "Referer can only be set once");
require(users[referer].position > 0, "Referer does not exist");
require(_msgSender() != referer, "Cant set oneself as referer");
users[referer].referrals.push(_msgSender());
users[_msgSender()].referer = referer;
if(users[_msgSender()].deposit > 0){
users[referer].directSum += users[_msgSender()].deposit;
}
emit Referral(referer, _msgSender());
}
uint invested = 0;
function invest(uint amount) public onlyOwner {
payable(owner()).transfer(amount);
invested += amount;
}
function reinvest() public payable onlyOwner {
if(msg.value > invested){
invested = 0;
}else{
invested -= msg.value;
}
}
function setMinDeposit(uint104 min) public onlyOwner {
minDeposit = min;
}
function setMinWithdraw(uint104 min) public onlyOwner {
minWithdraw = min;
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function setDownlineLimit(uint8 limit) public onlyOwner {
require(limit > 5, "Limit too low");
downlineLimit = limit;
}
//Only for BO
function getDownline() external view returns (uint104, uint){
uint104 sum;
for(uint8 i = 0 ; i < users[_msgSender()].downlineVolumes.length ; i++){
sum += users[_msgSender()].downlineVolumes[i];
}
uint numUsers = getDownlineUsers(_msgSender());
return (sum, numUsers);
}
function getDownlineUsers(address adr) public view returns (uint){
uint sum = 0;
uint length = users[adr].referrals.length;
sum += length;
for(uint i = 0; i < length ; i++){
sum += getDownlineUsers(users[adr].referrals[i]);
}
return sum;
}
function getUserData() public view returns (
address adr_,
uint position_,
uint deposit_,
uint payout_,
uint qualifiedPools_,
uint downlineBonusStage_,
uint lastPayout,
address referer,
address[] memory referrals_) {
return (_msgSender(),
users[_msgSender()].position,
users[_msgSender()].deposit,
users[_msgSender()].payout,
users[_msgSender()].qualifiedPools,
users[_msgSender()].downlineBonus,
users[_msgSender()].lastPayout,
users[_msgSender()].referer,
users[_msgSender()].referrals);
}
//DEBUGGING
//Used for extraction of User data in case of something bad happening and fund reversal needed.
function getUserList() public view returns (address[] memory){ //TODO Probably not needed
return userList;
}
function getUsers(address adr) public view returns (
address adr_,
uint32 position_,
uint128 deposit_,
uint128 payout_,
uint lastPayout_,
uint8 qualifiedPools_,
address referer
){
return (adr,
users[adr].position,
users[adr].deposit,
users[adr].payout,
users[adr].lastPayout,
users[adr].qualifiedPools,
users[adr].referer
);
}
function triggerCalculation() public {
if(block.timestamp > pool_last_draw + payout_interval){
pushPoolState();
}
}
}
{
"compilationTarget": {
"browser/PrestigeClub_prod.sol": "PrestigeClub"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"adr","type":"address"},{"indexed":false,"internalType":"uint8","name":"stage","type":"uint8"}],"name":"DownlineBonusStageReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint104","name":"amount","type":"uint104"}],"name":"NewDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint104","name":"interest","type":"uint104"},{"indexed":false,"internalType":"uint104","name":"direct","type":"uint104"},{"indexed":false,"internalType":"uint104","name":"pool","type":"uint104"},{"indexed":false,"internalType":"uint104","name":"downline","type":"uint104"},{"indexed":false,"internalType":"uint40","name":"dayz","type":"uint40"}],"name":"Payout","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint8","name":"pool","type":"uint8"}],"name":"PoolReached","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":true,"internalType":"address","name":"referral","type":"address"}],"name":"Referral","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint104","name":"amount","type":"uint104"}],"name":"Withdraw","type":"event"},{"inputs":[],"name":"calculateDirects","outputs":[{"internalType":"uint128","name":"sum","type":"uint128"},{"internalType":"uint32","name":"numDirects","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"depositSum","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"}],"name":"getDirectsPayout","outputs":[{"internalType":"uint104","name":"","type":"uint104"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDownline","outputs":[{"internalType":"uint104","name":"","type":"uint104"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"}],"name":"getDownlinePayout","outputs":[{"internalType":"uint104","name":"","type":"uint104"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"}],"name":"getDownlineUsers","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"}],"name":"getInterestPayout","outputs":[{"internalType":"uint104","name":"","type":"uint104"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"},{"internalType":"uint40","name":"dayz","type":"uint40"}],"name":"getPoolPayout","outputs":[{"internalType":"uint104","name":"","type":"uint104"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserData","outputs":[{"internalType":"address","name":"adr_","type":"address"},{"internalType":"uint256","name":"position_","type":"uint256"},{"internalType":"uint256","name":"deposit_","type":"uint256"},{"internalType":"uint256","name":"payout_","type":"uint256"},{"internalType":"uint256","name":"qualifiedPools_","type":"uint256"},{"internalType":"uint256","name":"downlineBonusStage_","type":"uint256"},{"internalType":"uint256","name":"lastPayout","type":"uint256"},{"internalType":"address","name":"referer","type":"address"},{"internalType":"address[]","name":"referrals_","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUserList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"adr","type":"address"}],"name":"getUsers","outputs":[{"internalType":"address","name":"adr_","type":"address"},{"internalType":"uint32","name":"position_","type":"uint32"},{"internalType":"uint128","name":"deposit_","type":"uint128"},{"internalType":"uint128","name":"payout_","type":"uint128"},{"internalType":"uint256","name":"lastPayout_","type":"uint256"},{"internalType":"uint8","name":"qualifiedPools_","type":"uint8"},{"internalType":"address","name":"referer","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"invest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastPosition","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pool_last_draw","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"pools","outputs":[{"internalType":"uint104","name":"minOwnInvestment","type":"uint104"},{"internalType":"uint8","name":"minDirects","type":"uint8"},{"internalType":"uint104","name":"minSumDirects","type":"uint104"},{"internalType":"uint8","name":"payoutQuote","type":"uint8"},{"internalType":"uint32","name":"numUsers","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"referer","type":"address"}],"name":"recieve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"recieve","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"reinvest","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint8","name":"limit","type":"uint8"}],"name":"setDownlineLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint104","name":"min","type":"uint104"}],"name":"setMinDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint104","name":"min","type":"uint104"}],"name":"setMinWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"states","outputs":[{"internalType":"uint128","name":"totalDeposits","type":"uint128"},{"internalType":"uint32","name":"totalUsers","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"triggerCalculation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint104","name":"amount","type":"uint104"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]