Comparing sensitive data, confidential files or internal emails?

Most legal and privacy policies prohibit uploading sensitive data online. Diffchecker Desktop ensures your confidential information never leaves your computer. Work offline and compare documents securely.

Acropolis vs Masonry

Created Diff never expires
92 removals
266 lines
92 additions
266 lines
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT


pragma solidity 0.6.12;
pragma solidity ^0.8.0;


import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";


import "./utils/ContractGuard.sol";
import "./utils/ContractGuard.sol";
import "./interfaces/IBasisAsset.sol";
import "./interfaces/IBasisAsset.sol";
import "./interfaces/ITreasury.sol";
import "./interfaces/ITreasury.sol";


contract ShareWrapper {
contract ShareWrapper {
using SafeMath for uint256;
using SafeMath for uint256;
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;


IERC20 public share;
IERC20 public share;


uint256 private _totalSupply;
uint256 private _totalSupply;
mapping(address => uint256) private _balances;
mapping(address => uint256) private _balances;


function totalSupply() public view returns (uint256) {
function totalSupply() public view returns (uint256) {
return _totalSupply;
return _totalSupply;
}
}


function balanceOf(address account) public view returns (uint256) {
function balanceOf(address account) public view returns (uint256) {
return _balances[account];
return _balances[account];
}
}


function stake(uint256 amount) public virtual {
function stake(uint256 amount) public virtual {
_totalSupply = _totalSupply.add(amount);
_totalSupply = _totalSupply.add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
_balances[msg.sender] = _balances[msg.sender].add(amount);
share.safeTransferFrom(msg.sender, address(this), amount);
share.safeTransferFrom(msg.sender, address(this), amount);
}
}


function withdraw(uint256 amount) public virtual {
function withdraw(uint256 amount) public virtual {
uint256 masonShare = _balances[msg.sender];
uint256 andrasShare = _balances[msg.sender];
require(masonShare >= amount, "Masonry: withdraw request greater than staked amount");
require(andrasShare >= amount, "Acropolis: withdraw request greater than staked amount");
_totalSupply = _totalSupply.sub(amount);
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = masonShare.sub(amount);
_balances[msg.sender] = andrasShare.sub(amount);
share.safeTransfer(msg.sender, amount);
share.safeTransfer(msg.sender, amount);
}
}
}
}


/*
/*
______ __ _______
__________ .___ ___________.__
/_ __/___ ____ ___ / /_ / ____(_)___ ____ _____ ________
\______ \_____ ______ ____ __| _/ \_ _____/|__| ____ _____ ____ ____ ____
/ / / __ \/ __ `__ \/ __ \ / /_ / / __ \/ __ `/ __ \/ ___/ _ \
| | _/\__ \ / ___/_/ __ \ / __ | | __) | | / \ \__ \ / \ _/ ___\_/ __ \
/ / / /_/ / / / / / / /_/ / / __/ / / / / / /_/ / / / / /__/ __/
| | \ / __ \_ \___ \ \ ___/ / /_/ | | \ | || | \ / __ \_| | \\ \___\ ___/
/_/ \____/_/ /_/ /_/_.___/ /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/
|______ /(____ //____ > \___ >\____ | \___ / |__||___| /(____ /|___| / \___ >\___ >

\/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
http://tomb.finance
*/
*/
contract Masonry is ShareWrapper, ContractGuard {
contract Acropolis is ShareWrapper, ContractGuard {
using SafeERC20 for IERC20;
using SafeERC20 for IERC20;
using Address for address;
using Address for address;
using SafeMath for uint256;
using SafeMath for uint256;


/* ========== DATA STRUCTURES ========== */
/* ========== DATA STRUCTURES ========== */


struct Masonseat {
struct Ecclesiaseat {
uint256 lastSnapshotIndex;
uint256 lastSnapshotIndex;
uint256 rewardEarned;
uint256 rewardEarned;
uint256 epochTimerStart;
uint256 epochTimerStart;
}
}


struct MasonrySnapshot {
struct AcropolisSnapshot {
uint256 time;
uint256 time;
uint256 rewardReceived;
uint256 rewardReceived;
uint256 rewardPerShare;
uint256 rewardPerShare;
}
}


/* ========== STATE VARIABLES ========== */
/* ========== STATE VARIABLES ========== */


// governance
// governance
address public operator;
address public operator;


// flags
// flags
bool public initialized = false;
bool public initialized = false;


IERC20 public tomb;
IERC20 public based;
ITreasury public treasury;
ITreasury public treasury;


mapping(address => Masonseat) public masons;
mapping(address => Ecclesiaseat) public demos;
MasonrySnapshot[] public masonryHistory;
AcropolisSnapshot[] public acropolisHistory;


uint256 public withdrawLockupEpochs;
uint256 public withdrawLockupEpochs;
uint256 public rewardLockupEpochs;
uint256 public rewardLockupEpochs;


/* ========== EVENTS ========== */
/* ========== EVENTS ========== */


event Initialized(address indexed executor, uint256 at);
event Initialized(address indexed executor, uint256 at);
event Staked(address indexed user, uint256 amount);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
event RewardPaid(address indexed user, uint256 reward);
event RewardAdded(address indexed user, uint256 reward);
event RewardAdded(address indexed user, uint256 reward);


/* ========== Modifiers =============== */
/* ========== Modifiers =============== */


modifier onlyOperator() {
modifier onlyOperator() {
require(operator == msg.sender, "Masonry: caller is not the operator");
require(operator == msg.sender, "Acropolis: caller is not the operator");
_;
_;
}
}


modifier masonExists {
modifier andrasExists {
require(balanceOf(msg.sender) > 0, "Masonry: The mason does not exist");
require(balanceOf(msg.sender) > 0, "Acropolis: The andras does not exist");
_;
_;
}
}


modifier updateReward(address mason) {
modifier updateReward(address andras) {
if (mason != address(0)) {
if (andras != address(0)) {
Masonseat memory seat = masons[mason];
Ecclesiaseat memory seat = demos[andras];
seat.rewardEarned = earned(mason);
seat.rewardEarned = earned(andras);
seat.lastSnapshotIndex = latestSnapshotIndex();
seat.lastSnapshotIndex = latestSnapshotIndex();
masons[mason] = seat;
demos[andras] = seat;
}
}
_;
_;
}
}


modifier notInitialized {
modifier notInitialized {
require(!initialized, "Masonry: already initialized");
require(!initialized, "Acropolis: already initialized");
_;
_;
}
}


/* ========== GOVERNANCE ========== */
/* ========== GOVERNANCE ========== */


function initialize(
function initialize(
IERC20 _tomb,
IERC20 _based,
IERC20 _share,
IERC20 _share,
ITreasury _treasury
ITreasury _treasury
) public notInitialized {
) public notInitialized {
tomb = _tomb;
based = _based;
share = _share;
share = _share;
treasury = _treasury;
treasury = _treasury;


MasonrySnapshot memory genesisSnapshot = MasonrySnapshot({time : block.number, rewardReceived : 0, rewardPerShare : 0});
AcropolisSnapshot memory genesisSnapshot = AcropolisSnapshot({time : block.number, rewardReceived : 0, rewardPerShare : 0});
masonryHistory.push(genesisSnapshot);
acropolisHistory.push(genesisSnapshot);


withdrawLockupEpochs = 6; // Lock for 6 epochs (36h) before release withdraw
withdrawLockupEpochs = 4; // Lock for 6 epochs (36h) before release withdraw
rewardLockupEpochs = 3; // Lock for 3 epochs (18h) before release claimReward
rewardLockupEpochs = 2; // Lock for 3 epochs (18h) before release claimReward !!! THIS IS ALTERED TO SMALLER PERIODS


initialized = true;
initialized = true;
operator = msg.sender;
operator = msg.sender;
emit Initialized(msg.sender, block.number);
emit Initialized(msg.sender, block.number);
}
}


function setOperator(address _operator) external onlyOperator {
function setOperator(address _operator) external onlyOperator {
operator = _operator;
operator = _operator;
}
}


function setLockUp(uint256 _withdrawLockupEpochs, uint256 _rewardLockupEpochs) external onlyOperator {
function setLockUp(uint256 _withdrawLockupEpochs, uint256 _rewardLockupEpochs) external onlyOperator {
require(_withdrawLockupEpochs >= _rewardLockupEpochs && _withdrawLockupEpochs <= 56, "_withdrawLockupEpochs: out of range"); // <= 2 week
require(_withdrawLockupEpochs >= _rewardLockupEpochs && _withdrawLockupEpochs <= 56, "_withdrawLockupEpochs: out of range"); // <= 2 week
withdrawLockupEpochs = _withdrawLockupEpochs;
withdrawLockupEpochs = _withdrawLockupEpochs;
rewardLockupEpochs = _rewardLockupEpochs;
rewardLockupEpochs = _rewardLockupEpochs;
}
}


/* ========== VIEW FUNCTIONS ========== */
/* ========== VIEW FUNCTIONS ========== */


// =========== Snapshot getters
// =========== Snapshot getters =========== //


function latestSnapshotIndex() public view returns (uint256) {
function latestSnapshotIndex() public view returns (uint256) {
return masonryHistory.length.sub(1);
return acropolisHistory.length.sub(1);
}
}


function getLatestSnapshot() internal view returns (MasonrySnapshot memory) {
function getLatestSnapshot() internal view returns (AcropolisSnapshot memory) {
return masonryHistory[latestSnapshotIndex()];
return acropolisHistory[latestSnapshotIndex()];
}
}


function getLastSnapshotIndexOf(address mason) public view returns (uint256) {
function getLastSnapshotIndexOf(address andras) public view returns (uint256) {
return masons[mason].lastSnapshotIndex;
return demos[andras].lastSnapshotIndex;
}
}


function getLastSnapshotOf(address mason) internal view returns (MasonrySnapshot memory) {
function getLastSnapshotOf(address andras) internal view returns (AcropolisSnapshot memory) {
return masonryHistory[getLastSnapshotIndexOf(mason)];
return acropolisHistory[getLastSnapshotIndexOf(andras)];
}
}


function canWithdraw(address mason) external view returns (bool) {
function canWithdraw(address andras) external view returns (bool) {
return masons[mason].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch();
return demos[andras].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch();
}
}


function canClaimReward(address mason) external view returns (bool) {
function canClaimReward(address andras) external view returns (bool) {
return masons[mason].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch();
return demos[andras].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch();
}
}


function epoch() external view returns (uint256) {
function epoch() external view returns (uint256) {
return treasury.epoch();
return treasury.epoch();
}
}


function nextEpochPoint() external view returns (uint256) {
function nextEpochPoint() external view returns (uint256) {
return treasury.nextEpochPoint();
return treasury.nextEpochPoint();
}
}


function getTombPrice() external view returns (uint256) {
function getBasedPrice() external view returns (uint256) {
return treasury.getTombPrice();
return treasury.getBasedPrice();
}
}


// =========== Mason getters
// =========== Andras getters =========== //


function rewardPerShare() public view returns (uint256) {
function rewardPerShare() public view returns (uint256) {
return getLatestSnapshot().rewardPerShare;
return getLatestSnapshot().rewardPerShare;
}
}


function earned(address mason) public view returns (uint256) {
function earned(address andras) public view returns (uint256) {
uint256 latestRPS = getLatestSnapshot().rewardPerShare;
uint256 latestRPS = getLatestSnapshot().rewardPerShare;
uint256 storedRPS = getLastSnapshotOf(mason).rewardPerShare;
uint256 storedRPS = getLastSnapshotOf(andras).rewardPerShare;


return balanceOf(mason).mul(latestRPS.sub(storedRPS)).div(1e18).add(masons[mason].rewardEarned);
return balanceOf(andras).mul(latestRPS.sub(storedRPS)).div(1e18).add(demos[andras].rewardEarned);
}
}


/* ========== MUTATIVE FUNCTIONS ========== */
/* ========== MUTATIVE FUNCTIONS ========== */


function stake(uint256 amount) public override onlyOneBlock updateReward(msg.sender) {
function stake(uint256 amount) public override onlyOneBlock updateReward(msg.sender) {
require(amount > 0, "Masonry: Cannot stake 0");
require(amount > 0, "Acropolis: Cannot stake 0");
super.stake(amount);
super.stake(amount);
masons[msg.sender].epochTimerStart = treasury.epoch(); // reset timer
demos[msg.sender].epochTimerStart = treasury.epoch(); // reset timer
emit Staked(msg.sender, amount);
emit Staked(msg.sender, amount);
}
}


function withdraw(uint256 amount) public override onlyOneBlock masonExists updateReward(msg.sender) {
function withdraw(uint256 amount) public override onlyOneBlock andrasExists updateReward(msg.sender) {
require(amount > 0, "Masonry: Cannot withdraw 0");
require(amount > 0, "Acropolis: Cannot withdraw 0");
require(masons[msg.sender].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch(), "Masonry: still in withdraw lockup");
require(demos[msg.sender].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch(), "Acropolis: still in withdraw lockup");
claimReward();
claimReward();
super.withdraw(amount);
super.withdraw(amount);
emit Withdrawn(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
}


function exit() external {
function exit() external {
withdraw(balanceOf(msg.sender));
withdraw(balanceOf(msg.sender));
}
}


function claimReward() public updateReward(msg.sender) {
function claimReward() public updateReward(msg.sender) {
uint256 reward = masons[msg.sender].rewardEarned;
uint256 reward = demos[msg.sender].rewardEarned;
if (reward > 0) {
if (reward > 0) {
require(masons[msg.sender].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch(), "Masonry: still in reward lockup");
require(demos[msg.sender].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch(), "Acropolis: still in reward lockup");
masons[msg.sender].epochTimerStart = treasury.epoch(); // reset timer
demos[msg.sender].epochTimerStart = treasury.epoch(); // reset timer
masons[msg.sender].rewardEarned = 0;
demos[msg.sender].rewardEarned = 0;
tomb.safeTransfer(msg.sender, reward);
based.safeTransfer(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
emit RewardPaid(msg.sender, reward);
}
}
}
}


function allocateSeigniorage(uint256 amount) external onlyOneBlock onlyOperator {
function allocateSeigniorage(uint256 amount) external onlyOneBlock onlyOperator {
require(amount > 0, "Masonry: Cannot allocate 0");
require(amount > 0, "Acropolis: Cannot allocate 0");
require(totalSupply() > 0, "Masonry: Cannot allocate when totalSupply is 0");
require(totalSupply() > 0, "Acropolis: Cannot allocate when totalSupply is 0");


// Create & add new snapshot
// Create & add new snapshot
uint256 prevRPS = getLatestSnapshot().rewardPerShare;
uint256 prevRPS = getLatestSnapshot().rewardPerShare;
uint256 nextRPS = prevRPS.add(amount.mul(1e18).div(totalSupply()));
uint256 nextRPS = prevRPS.add(amount.mul(1e18).div(totalSupply()));


MasonrySnapshot memory newSnapshot = MasonrySnapshot({
AcropolisSnapshot memory newSnapshot = AcropolisSnapshot({
time: block.number,
time: block.number,
rewardReceived: amount,
rewardReceived: amount,
rewardPerShare: nextRPS
rewardPerShare: nextRPS
});
});
masonryHistory.push(newSnapshot);
acropolisHistory.push(newSnapshot);


tomb.safeTransferFrom(msg.sender, address(this), amount);
based.safeTransferFrom(msg.sender, address(this), amount);
emit RewardAdded(msg.sender, amount);
emit RewardAdded(msg.sender, amount);
}
}


function governanceRecoverUnsupported(IERC20 _token, uint256 _amount, address _to) external onlyOperator {
function governanceRecoverUnsupported(IERC20 _token, uint256 _amount, address _to) external onlyOperator {
// do not allow to drain core tokens
// do not allow to drain core tokens
require(address(_token) != address(tomb), "tomb");
require(address(_token) != address(based), "based");
require(address(_token) != address(share), "share");
require(address(_token) != address(share), "share");
_token.safeTransfer(_to, _amount);
_token.safeTransfer(_to, _amount);
}
}
}
}