Diff
checker
Texto
Texto
Imagens
Documentos
Excel
Pastas
Legal
Enterprise
Aplicativo para desktop
Preços
Fazer login
Baixar o Diffchecker Desktop
Comparar texto
Encontre a diferença entre dois arquivos de texto
Ferramentas
Histórico
Editor live
Recolher inalteradas
Sem quebra de linha
Layout
Dividido
Unificado
Nível de detalhe
Inteligente
Palavra
Caractere
Realce de sintaxe
Escolher sintaxe
Ignorar
Transformar texto
Ir à primeira mudança
Editar entrada
Diffchecker Desktop
A maneira mais segura de usar o Diffchecker. Obtenha o aplicativo Diffchecker Desktop: seus diffs nunca saem do seu computador!
Obter Desktop
Acropolis vs Masonry
Criado
há 4 anos
O diff nunca expira
Limpar
Exportar
Compartilhar
Explicar
100 remoções
Linhas
Total
Removido
Caracteres
Total
Removido
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
266 linhas
Copiar tudo
107 adições
Linhas
Total
Adicionado
Caracteres
Total
Adicionado
Para continuar usando este recurso, atualize para
Diff
checker
Pro
Ver preços
266 linhas
Copiar tudo
// SPDX-License-Identifier: MIT
// SPDX-License-Identifier: MIT
Copiar
Copiado
Copiar
Copiado
pragma solidity
0.6.12
;
pragma solidity
^0.8.0
;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
Copiar
Copiado
Copiar
Copiado
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 {
Copiar
Copiado
Copiar
Copiado
uint256
mason
Share = _balances[msg.sender];
uint256
andras
Share = _balances[msg.sender];
require(
mason
Share >= amount, "
Masonry
: withdraw request greater than staked amount");
require(
andras
Share >= amount, "
Acropolis
: withdraw request greater than staked amount");
_totalSupply = _totalSupply.sub(amount);
_totalSupply = _totalSupply.sub(amount);
Copiar
Copiado
Copiar
Copiado
_balances[msg.sender] =
mason
Share.sub(amount);
_balances[msg.sender] =
andras
Share.sub(amount);
share.safeTransfer(msg.sender, amount);
share.safeTransfer(msg.sender, amount);
}
}
}
}
/*
/*
Copiar
Copiado
Copiar
Copiado
______
__
_______
____
______
.___ ____
_______
.__
/
_
__/
___ ____
___ / /
_
/
____
(_)
___ ____
____
_
____
____
\______ \____
_
___
___ ____
__| _/ \
_
____
_/|__| _
___ ____
_
____
____
____
/
/
/ __ \
/ __
`__ \/
__
\ /
/_ /
/ __ \
/ __
`/
__ \
/
___/
_ \
| | _/\__ \
/
___/_
/ __ \
/ __
| | __) | | / \ \
__
\ /
\ _/ ___\_
/ __ \
/ /
/ /_/
/ / / / / / /_/ /
/ __
/ / / / / / /_/ / / / /
/__
/ __/
| | \
/ __
\_ \_
__ \
\
___/
/ /_/
| | \ | || | \
/ __
\_| | \\ \___\ ___/
/_/
\____
/_/ /_/ /_/_.
___
/
/
_/
/_/_/ /_/\__,_/_/ /_/
\___
/
\___
/
|______ /(____ /
/__
__ > \___ >
\____
| \
___
/
|__||___| /(____ /|___| /
\___
>
\___
>
\/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/
http://tomb.finance
*/
*/
Copiar
Copiado
Copiar
Copiado
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 ========== */
Copiar
Copiado
Copiar
Copiado
struct
Masonseat
{
struct
Ecclesiaseat
{
uint256 lastSnapshotIndex;
uint256 lastSnapshotIndex;
uint256 rewardEarned;
uint256 rewardEarned;
uint256 epochTimerStart;
uint256 epochTimerStart;
}
}
Copiar
Copiado
Copiar
Copiado
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;
Copiar
Copiado
Copiar
Copiado
IERC20 public
tomb
;
IERC20 public
based
;
ITreasury public treasury;
ITreasury public treasury;
Copiar
Copiado
Copiar
Copiado
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() {
Copiar
Copiado
Copiar
Copiado
require(operator == msg.sender, "
Masonry
: caller is not the operator");
require(operator == msg.sender, "
Acropolis
: caller is not the operator");
_;
_;
}
}
Copiar
Copiado
Copiar
Copiado
modifier
mason
Exists {
modifier
andras
Exists {
require(balanceOf(msg.sender) > 0, "
Masonry
: The
mason
does not exist");
require(balanceOf(msg.sender) > 0, "
Acropolis
: The
andras
does not exist");
_;
_;
}
}
Copiar
Copiado
Copiar
Copiado
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();
Copiar
Copiado
Copiar
Copiado
masons[mason
] = seat;
demos[andras
] = seat;
}
}
_;
_;
}
}
modifier notInitialized {
modifier notInitialized {
Copiar
Copiado
Copiar
Copiado
require(!initialized, "
Masonry
: already initialized");
require(!initialized, "
Acropolis
: already initialized");
_;
_;
}
}
/* ========== GOVERNANCE ========== */
/* ========== GOVERNANCE ========== */
function initialize(
function initialize(
Copiar
Copiado
Copiar
Copiado
IERC20 _
tomb
,
IERC20 _
based
,
IERC20 _share,
IERC20 _share,
ITreasury _treasury
ITreasury _treasury
) public notInitialized {
) public notInitialized {
Copiar
Copiado
Copiar
Copiado
tomb
= _
tomb
;
based
= _
based
;
share = _share;
share = _share;
treasury = _treasury;
treasury = _treasury;
Copiar
Copiado
Copiar
Copiado
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);
Copiar
Copiado
Copiar
Copiado
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 ========== */
Copiar
Copiado
Copiar
Copiado
// =========== Snapshot getters
// =========== Snapshot getters
=========== //
function latestSnapshotIndex() public view returns (uint256) {
function latestSnapshotIndex() public view returns (uint256) {
Copiar
Copiado
Copiar
Copiado
return
masonryHistory
.length.sub(1);
return
acropolisHistory
.length.sub(1);
}
}
Copiar
Copiado
Copiar
Copiado
function getLatestSnapshot() internal view returns (
MasonrySnapshot
memory) {
function getLatestSnapshot() internal view returns (
AcropolisSnapshot
memory) {
return
masonryHistory
[latestSnapshotIndex()];
return
acropolisHistory
[latestSnapshotIndex()];
}
}
Copiar
Copiado
Copiar
Copiado
function getLastSnapshotIndexOf(address
mason
) public view returns (uint256) {
function getLastSnapshotIndexOf(address
andras
) public view returns (uint256) {
return
masons[mason
].lastSnapshotIndex;
return
demos[andras
].lastSnapshotIndex;
}
}
Copiar
Copiado
Copiar
Copiado
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
)];
}
}
Copiar
Copiado
Copiar
Copiado
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();
}
}
Copiar
Copiado
Copiar
Copiado
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();
}
}
Copiar
Copiado
Copiar
Copiado
function
getTombPrice
() external view returns (uint256) {
function
getBasedPrice
() external view returns (uint256) {
return treasury.
getTombPrice
();
return treasury.
getBasedPrice
();
}
}
Copiar
Copiado
Copiar
Copiado
// ===========
Mason
getters
// ===========
Andras
getters
=========== //
function rewardPerShare() public view returns (uint256) {
function rewardPerShare() public view returns (uint256) {
return getLatestSnapshot().rewardPerShare;
return getLatestSnapshot().rewardPerShare;
}
}
Copiar
Copiado
Copiar
Copiado
function earned(address
mason
) public view returns (uint256) {
function earned(address
andras
) public view returns (uint256) {
uint256 latestRPS = getLatestSnapshot().rewardPerShare;
uint256 latestRPS = getLatestSnapshot().rewardPerShare;
Copiar
Copiado
Copiar
Copiado
uint256 storedRPS = getLastSnapshotOf(
mason
).rewardPerShare;
uint256 storedRPS = getLastSnapshotOf(
andras
).rewardPerShare;
Copiar
Copiado
Copiar
Copiado
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) {
Copiar
Copiado
Copiar
Copiado
require(amount > 0, "
Masonry
: Cannot stake 0");
require(amount > 0, "
Acropolis
: Cannot stake 0");
super.stake(amount);
super.stake(amount);
Copiar
Copiado
Copiar
Copiado
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);
}
}
Copiar
Copiado
Copiar
Copiado
function withdraw(uint256 amount) public override onlyOneBlock
mason
Exists updateReward(msg.sender) {
function withdraw(uint256 amount) public override onlyOneBlock
andras
Exists 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) {
Copiar
Copiado
Copiar
Copiado
uint256 reward =
masons
[msg.sender].rewardEarned;
uint256 reward =
demos
[msg.sender].rewardEarned;
if (reward > 0) {
if (reward > 0) {
Copiar
Copiado
Copiar
Copiado
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 {
Copiar
Copiado
Copiar
Copiado
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()));
Copiar
Copiado
Copiar
Copiado
MasonrySnapshot
memory newSnapshot =
MasonrySnapshot
({
AcropolisSnapshot
memory newSnapshot =
AcropolisSnapshot
({
time: block.number,
time: block.number,
rewardReceived: amount,
rewardReceived: amount,
rewardPerShare: nextRPS
rewardPerShare: nextRPS
});
});
Copiar
Copiado
Copiar
Copiado
masonryHistory
.push(newSnapshot);
acropolisHistory
.push(newSnapshot);
Copiar
Copiado
Copiar
Copiado
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
Copiar
Copiado
Copiar
Copiado
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);
}
}
}
}
Diferenças salvas
Texto original
Abrir arquivo
// SPDX-License-Identifier: MIT pragma solidity 0.6.12; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; import "./utils/ContractGuard.sol"; import "./interfaces/IBasisAsset.sol"; import "./interfaces/ITreasury.sol"; contract ShareWrapper { using SafeMath for uint256; using SafeERC20 for IERC20; IERC20 public share; uint256 private _totalSupply; mapping(address => uint256) private _balances; function totalSupply() public view returns (uint256) { return _totalSupply; } function balanceOf(address account) public view returns (uint256) { return _balances[account]; } function stake(uint256 amount) public virtual { _totalSupply = _totalSupply.add(amount); _balances[msg.sender] = _balances[msg.sender].add(amount); share.safeTransferFrom(msg.sender, address(this), amount); } function withdraw(uint256 amount) public virtual { uint256 masonShare = _balances[msg.sender]; require(masonShare >= amount, "Masonry: withdraw request greater than staked amount"); _totalSupply = _totalSupply.sub(amount); _balances[msg.sender] = masonShare.sub(amount); share.safeTransfer(msg.sender, amount); } } /* ______ __ _______ /_ __/___ ____ ___ / /_ / ____(_)___ ____ _____ ________ / / / __ \/ __ `__ \/ __ \ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ / / / /_/ / / / / / / /_/ / / __/ / / / / / /_/ / / / / /__/ __/ /_/ \____/_/ /_/ /_/_.___/ /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ http://tomb.finance */ contract Masonry is ShareWrapper, ContractGuard { using SafeERC20 for IERC20; using Address for address; using SafeMath for uint256; /* ========== DATA STRUCTURES ========== */ struct Masonseat { uint256 lastSnapshotIndex; uint256 rewardEarned; uint256 epochTimerStart; } struct MasonrySnapshot { uint256 time; uint256 rewardReceived; uint256 rewardPerShare; } /* ========== STATE VARIABLES ========== */ // governance address public operator; // flags bool public initialized = false; IERC20 public tomb; ITreasury public treasury; mapping(address => Masonseat) public masons; MasonrySnapshot[] public masonryHistory; uint256 public withdrawLockupEpochs; uint256 public rewardLockupEpochs; /* ========== EVENTS ========== */ event Initialized(address indexed executor, uint256 at); event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardPaid(address indexed user, uint256 reward); event RewardAdded(address indexed user, uint256 reward); /* ========== Modifiers =============== */ modifier onlyOperator() { require(operator == msg.sender, "Masonry: caller is not the operator"); _; } modifier masonExists { require(balanceOf(msg.sender) > 0, "Masonry: The mason does not exist"); _; } modifier updateReward(address mason) { if (mason != address(0)) { Masonseat memory seat = masons[mason]; seat.rewardEarned = earned(mason); seat.lastSnapshotIndex = latestSnapshotIndex(); masons[mason] = seat; } _; } modifier notInitialized { require(!initialized, "Masonry: already initialized"); _; } /* ========== GOVERNANCE ========== */ function initialize( IERC20 _tomb, IERC20 _share, ITreasury _treasury ) public notInitialized { tomb = _tomb; share = _share; treasury = _treasury; MasonrySnapshot memory genesisSnapshot = MasonrySnapshot({time : block.number, rewardReceived : 0, rewardPerShare : 0}); masonryHistory.push(genesisSnapshot); withdrawLockupEpochs = 6; // Lock for 6 epochs (36h) before release withdraw rewardLockupEpochs = 3; // Lock for 3 epochs (18h) before release claimReward initialized = true; operator = msg.sender; emit Initialized(msg.sender, block.number); } function setOperator(address _operator) external onlyOperator { operator = _operator; } function setLockUp(uint256 _withdrawLockupEpochs, uint256 _rewardLockupEpochs) external onlyOperator { require(_withdrawLockupEpochs >= _rewardLockupEpochs && _withdrawLockupEpochs <= 56, "_withdrawLockupEpochs: out of range"); // <= 2 week withdrawLockupEpochs = _withdrawLockupEpochs; rewardLockupEpochs = _rewardLockupEpochs; } /* ========== VIEW FUNCTIONS ========== */ // =========== Snapshot getters function latestSnapshotIndex() public view returns (uint256) { return masonryHistory.length.sub(1); } function getLatestSnapshot() internal view returns (MasonrySnapshot memory) { return masonryHistory[latestSnapshotIndex()]; } function getLastSnapshotIndexOf(address mason) public view returns (uint256) { return masons[mason].lastSnapshotIndex; } function getLastSnapshotOf(address mason) internal view returns (MasonrySnapshot memory) { return masonryHistory[getLastSnapshotIndexOf(mason)]; } function canWithdraw(address mason) external view returns (bool) { return masons[mason].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch(); } function canClaimReward(address mason) external view returns (bool) { return masons[mason].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch(); } function epoch() external view returns (uint256) { return treasury.epoch(); } function nextEpochPoint() external view returns (uint256) { return treasury.nextEpochPoint(); } function getTombPrice() external view returns (uint256) { return treasury.getTombPrice(); } // =========== Mason getters function rewardPerShare() public view returns (uint256) { return getLatestSnapshot().rewardPerShare; } function earned(address mason) public view returns (uint256) { uint256 latestRPS = getLatestSnapshot().rewardPerShare; uint256 storedRPS = getLastSnapshotOf(mason).rewardPerShare; return balanceOf(mason).mul(latestRPS.sub(storedRPS)).div(1e18).add(masons[mason].rewardEarned); } /* ========== MUTATIVE FUNCTIONS ========== */ function stake(uint256 amount) public override onlyOneBlock updateReward(msg.sender) { require(amount > 0, "Masonry: Cannot stake 0"); super.stake(amount); masons[msg.sender].epochTimerStart = treasury.epoch(); // reset timer emit Staked(msg.sender, amount); } function withdraw(uint256 amount) public override onlyOneBlock masonExists updateReward(msg.sender) { require(amount > 0, "Masonry: Cannot withdraw 0"); require(masons[msg.sender].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch(), "Masonry: still in withdraw lockup"); claimReward(); super.withdraw(amount); emit Withdrawn(msg.sender, amount); } function exit() external { withdraw(balanceOf(msg.sender)); } function claimReward() public updateReward(msg.sender) { uint256 reward = masons[msg.sender].rewardEarned; if (reward > 0) { require(masons[msg.sender].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch(), "Masonry: still in reward lockup"); masons[msg.sender].epochTimerStart = treasury.epoch(); // reset timer masons[msg.sender].rewardEarned = 0; tomb.safeTransfer(msg.sender, reward); emit RewardPaid(msg.sender, reward); } } function allocateSeigniorage(uint256 amount) external onlyOneBlock onlyOperator { require(amount > 0, "Masonry: Cannot allocate 0"); require(totalSupply() > 0, "Masonry: Cannot allocate when totalSupply is 0"); // Create & add new snapshot uint256 prevRPS = getLatestSnapshot().rewardPerShare; uint256 nextRPS = prevRPS.add(amount.mul(1e18).div(totalSupply())); MasonrySnapshot memory newSnapshot = MasonrySnapshot({ time: block.number, rewardReceived: amount, rewardPerShare: nextRPS }); masonryHistory.push(newSnapshot); tomb.safeTransferFrom(msg.sender, address(this), amount); emit RewardAdded(msg.sender, amount); } function governanceRecoverUnsupported(IERC20 _token, uint256 _amount, address _to) external onlyOperator { // do not allow to drain core tokens require(address(_token) != address(tomb), "tomb"); require(address(_token) != address(share), "share"); _token.safeTransfer(_to, _amount); } }
Texto alterado
Abrir arquivo
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "./utils/ContractGuard.sol"; import "./interfaces/IBasisAsset.sol"; import "./interfaces/ITreasury.sol"; contract ShareWrapper { using SafeMath for uint256; using SafeERC20 for IERC20; IERC20 public share; uint256 private _totalSupply; mapping(address => uint256) private _balances; function totalSupply() public view returns (uint256) { return _totalSupply; } function balanceOf(address account) public view returns (uint256) { return _balances[account]; } function stake(uint256 amount) public virtual { _totalSupply = _totalSupply.add(amount); _balances[msg.sender] = _balances[msg.sender].add(amount); share.safeTransferFrom(msg.sender, address(this), amount); } function withdraw(uint256 amount) public virtual { uint256 andrasShare = _balances[msg.sender]; require(andrasShare >= amount, "Acropolis: withdraw request greater than staked amount"); _totalSupply = _totalSupply.sub(amount); _balances[msg.sender] = andrasShare.sub(amount); share.safeTransfer(msg.sender, amount); } } /* __________ .___ ___________.__ \______ \_____ ______ ____ __| _/ \_ _____/|__| ____ _____ ____ ____ ____ | | _/\__ \ / ___/_/ __ \ / __ | | __) | | / \ \__ \ / \ _/ ___\_/ __ \ | | \ / __ \_ \___ \ \ ___/ / /_/ | | \ | || | \ / __ \_| | \\ \___\ ___/ |______ /(____ //____ > \___ >\____ | \___ / |__||___| /(____ /|___| / \___ >\___ > \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ */ contract Acropolis is ShareWrapper, ContractGuard { using SafeERC20 for IERC20; using Address for address; using SafeMath for uint256; /* ========== DATA STRUCTURES ========== */ struct Ecclesiaseat { uint256 lastSnapshotIndex; uint256 rewardEarned; uint256 epochTimerStart; } struct AcropolisSnapshot { uint256 time; uint256 rewardReceived; uint256 rewardPerShare; } /* ========== STATE VARIABLES ========== */ // governance address public operator; // flags bool public initialized = false; IERC20 public based; ITreasury public treasury; mapping(address => Ecclesiaseat) public demos; AcropolisSnapshot[] public acropolisHistory; uint256 public withdrawLockupEpochs; uint256 public rewardLockupEpochs; /* ========== EVENTS ========== */ event Initialized(address indexed executor, uint256 at); event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardPaid(address indexed user, uint256 reward); event RewardAdded(address indexed user, uint256 reward); /* ========== Modifiers =============== */ modifier onlyOperator() { require(operator == msg.sender, "Acropolis: caller is not the operator"); _; } modifier andrasExists { require(balanceOf(msg.sender) > 0, "Acropolis: The andras does not exist"); _; } modifier updateReward(address andras) { if (andras != address(0)) { Ecclesiaseat memory seat = demos[andras]; seat.rewardEarned = earned(andras); seat.lastSnapshotIndex = latestSnapshotIndex(); demos[andras] = seat; } _; } modifier notInitialized { require(!initialized, "Acropolis: already initialized"); _; } /* ========== GOVERNANCE ========== */ function initialize( IERC20 _based, IERC20 _share, ITreasury _treasury ) public notInitialized { based = _based; share = _share; treasury = _treasury; AcropolisSnapshot memory genesisSnapshot = AcropolisSnapshot({time : block.number, rewardReceived : 0, rewardPerShare : 0}); acropolisHistory.push(genesisSnapshot); withdrawLockupEpochs = 4; // Lock for 6 epochs (36h) before release withdraw rewardLockupEpochs = 2; // Lock for 3 epochs (18h) before release claimReward !!! THIS IS ALTERED TO SMALLER PERIODS initialized = true; operator = msg.sender; emit Initialized(msg.sender, block.number); } function setOperator(address _operator) external onlyOperator { operator = _operator; } function setLockUp(uint256 _withdrawLockupEpochs, uint256 _rewardLockupEpochs) external onlyOperator { require(_withdrawLockupEpochs >= _rewardLockupEpochs && _withdrawLockupEpochs <= 56, "_withdrawLockupEpochs: out of range"); // <= 2 week withdrawLockupEpochs = _withdrawLockupEpochs; rewardLockupEpochs = _rewardLockupEpochs; } /* ========== VIEW FUNCTIONS ========== */ // =========== Snapshot getters =========== // function latestSnapshotIndex() public view returns (uint256) { return acropolisHistory.length.sub(1); } function getLatestSnapshot() internal view returns (AcropolisSnapshot memory) { return acropolisHistory[latestSnapshotIndex()]; } function getLastSnapshotIndexOf(address andras) public view returns (uint256) { return demos[andras].lastSnapshotIndex; } function getLastSnapshotOf(address andras) internal view returns (AcropolisSnapshot memory) { return acropolisHistory[getLastSnapshotIndexOf(andras)]; } function canWithdraw(address andras) external view returns (bool) { return demos[andras].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch(); } function canClaimReward(address andras) external view returns (bool) { return demos[andras].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch(); } function epoch() external view returns (uint256) { return treasury.epoch(); } function nextEpochPoint() external view returns (uint256) { return treasury.nextEpochPoint(); } function getBasedPrice() external view returns (uint256) { return treasury.getBasedPrice(); } // =========== Andras getters =========== // function rewardPerShare() public view returns (uint256) { return getLatestSnapshot().rewardPerShare; } function earned(address andras) public view returns (uint256) { uint256 latestRPS = getLatestSnapshot().rewardPerShare; uint256 storedRPS = getLastSnapshotOf(andras).rewardPerShare; return balanceOf(andras).mul(latestRPS.sub(storedRPS)).div(1e18).add(demos[andras].rewardEarned); } /* ========== MUTATIVE FUNCTIONS ========== */ function stake(uint256 amount) public override onlyOneBlock updateReward(msg.sender) { require(amount > 0, "Acropolis: Cannot stake 0"); super.stake(amount); demos[msg.sender].epochTimerStart = treasury.epoch(); // reset timer emit Staked(msg.sender, amount); } function withdraw(uint256 amount) public override onlyOneBlock andrasExists updateReward(msg.sender) { require(amount > 0, "Acropolis: Cannot withdraw 0"); require(demos[msg.sender].epochTimerStart.add(withdrawLockupEpochs) <= treasury.epoch(), "Acropolis: still in withdraw lockup"); claimReward(); super.withdraw(amount); emit Withdrawn(msg.sender, amount); } function exit() external { withdraw(balanceOf(msg.sender)); } function claimReward() public updateReward(msg.sender) { uint256 reward = demos[msg.sender].rewardEarned; if (reward > 0) { require(demos[msg.sender].epochTimerStart.add(rewardLockupEpochs) <= treasury.epoch(), "Acropolis: still in reward lockup"); demos[msg.sender].epochTimerStart = treasury.epoch(); // reset timer demos[msg.sender].rewardEarned = 0; based.safeTransfer(msg.sender, reward); emit RewardPaid(msg.sender, reward); } } function allocateSeigniorage(uint256 amount) external onlyOneBlock onlyOperator { require(amount > 0, "Acropolis: Cannot allocate 0"); require(totalSupply() > 0, "Acropolis: Cannot allocate when totalSupply is 0"); // Create & add new snapshot uint256 prevRPS = getLatestSnapshot().rewardPerShare; uint256 nextRPS = prevRPS.add(amount.mul(1e18).div(totalSupply())); AcropolisSnapshot memory newSnapshot = AcropolisSnapshot({ time: block.number, rewardReceived: amount, rewardPerShare: nextRPS }); acropolisHistory.push(newSnapshot); based.safeTransferFrom(msg.sender, address(this), amount); emit RewardAdded(msg.sender, amount); } function governanceRecoverUnsupported(IERC20 _token, uint256 _amount, address _to) external onlyOperator { // do not allow to drain core tokens require(address(_token) != address(based), "based"); require(address(_token) != address(share), "share"); _token.safeTransfer(_to, _amount); } }
Encontrar Diferença