mirror of https://github.com/nucypher/nucypher.git
Solidity 0.7.x -> 0.8.x, integration StakingEscrow with Threshold Network, updated OpenZeppelin library
parent
4dda3141ed
commit
5ced61f337
|
@ -15,4 +15,4 @@ You should have received a copy of the GNU Affero General Public License
|
|||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
SOLIDITY_COMPILER_VERSION = 'v0.7.6'
|
||||
SOLIDITY_COMPILER_VERSION = 'v0.8.10'
|
||||
|
|
|
@ -19,7 +19,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
from typing import List, Dict
|
||||
|
||||
from nucypher.blockchain.eth.sol.compile.constants import (
|
||||
CONTRACTS, ZEPPELIN, ARAGON
|
||||
CONTRACTS, ZEPPELIN, ARAGON, THRESHOLD
|
||||
)
|
||||
from nucypher.blockchain.eth.sol.compile.types import CompilerConfiguration
|
||||
|
||||
|
@ -114,7 +114,7 @@ COMPILER_SETTINGS: Dict = dict(
|
|||
outputSelection={"*": {"*": CONTRACT_OUTPUTS, "": FILE_OUTPUTS}}, # all contacts(*), all files("")
|
||||
)
|
||||
|
||||
REMAPPINGS: List = [CONTRACTS, ZEPPELIN, ARAGON]
|
||||
REMAPPINGS: List = [CONTRACTS, ZEPPELIN, ARAGON, THRESHOLD]
|
||||
|
||||
# Base configuration for programmatic usage
|
||||
BASE_COMPILER_CONFIGURATION = CompilerConfiguration(
|
||||
|
|
|
@ -34,6 +34,7 @@ from nucypher.blockchain.eth import sol
|
|||
SOLIDITY_SOURCE_ROOT: Path = Path(sol.__file__).parent / 'source'
|
||||
ZEPPELIN = 'zeppelin'
|
||||
ARAGON = 'aragon'
|
||||
THRESHOLD = 'threshold'
|
||||
|
||||
# Do not compile contracts containing...
|
||||
IGNORE_CONTRACT_PREFIXES: Tuple[str, ...] = (
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
// Minimum interface to interact with Aragon's Aggregator
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "contracts/lib/ReEncryptionValidator.sol";
|
||||
import "contracts/lib/SignatureVerifier.sol";
|
||||
|
@ -156,7 +156,7 @@ contract Adjudicator is Upgradeable {
|
|||
|
||||
// 4. Extract worker address from stamp signature.
|
||||
address worker = SignatureVerifier.recover(
|
||||
SignatureVerifier.hashEIP191(stamp, byte(0x45)), // Currently, we use version E (0x45) of EIP191 signatures
|
||||
SignatureVerifier.hashEIP191(stamp, bytes1(0x45)), // Currently, we use version E (0x45) of EIP191 signatures
|
||||
_workerIdentityEvidence);
|
||||
address staker = escrow.stakerFromWorker(worker);
|
||||
require(staker != address(0), "Worker must be related to a staker");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "contracts/NuCypherToken.sol";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "zeppelin/token/ERC20/ERC20.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "zeppelin/token/ERC20/SafeERC20.sol";
|
||||
|
@ -270,7 +270,7 @@ contract PolicyManager is Upgradeable {
|
|||
|
||||
for (uint256 i = 0; i < _nodes.length; i++) {
|
||||
address node = _nodes[i];
|
||||
addFeeToNode(currentPeriod, endPeriod, node, feeRate, int256(feeRate));
|
||||
addFeeToNode(currentPeriod, endPeriod, node, feeRate, int256(uint256(feeRate)));
|
||||
policy.arrangements.push(ArrangementInfo(node, 0, 0));
|
||||
}
|
||||
}
|
||||
|
@ -345,7 +345,7 @@ contract PolicyManager is Upgradeable {
|
|||
!policy.disabled
|
||||
);
|
||||
|
||||
policy.sponsor = msg.sender;
|
||||
policy.sponsor = payable(msg.sender);
|
||||
policy.startTimestamp = uint64(block.timestamp);
|
||||
policy.endTimestamp = _endTimestamp;
|
||||
policy.feeRate = _feeRate;
|
||||
|
@ -476,7 +476,7 @@ contract PolicyManager is Upgradeable {
|
|||
* @notice Withdraw fee by node
|
||||
*/
|
||||
function withdraw() external returns (uint256) {
|
||||
return withdraw(msg.sender);
|
||||
return withdraw(payable(msg.sender));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -573,14 +573,14 @@ contract PolicyManager is Upgradeable {
|
|||
// Check default value for feeDelta
|
||||
uint16 lastRefundedPeriod = arrangement.lastRefundedPeriod;
|
||||
if (nodeInfo.feeDelta[lastRefundedPeriod] == DEFAULT_FEE_DELTA) {
|
||||
nodeInfo.feeDelta[lastRefundedPeriod] = -int256(policy.feeRate);
|
||||
nodeInfo.feeDelta[lastRefundedPeriod] = -int256(uint256(policy.feeRate));
|
||||
} else {
|
||||
nodeInfo.feeDelta[lastRefundedPeriod] -= int256(policy.feeRate);
|
||||
nodeInfo.feeDelta[lastRefundedPeriod] -= int256(uint256(policy.feeRate));
|
||||
}
|
||||
if (nodeInfo.feeDelta[endPeriod] == DEFAULT_FEE_DELTA) {
|
||||
nodeInfo.feeDelta[endPeriod] = int256(policy.feeRate);
|
||||
nodeInfo.feeDelta[endPeriod] = int256(uint256(policy.feeRate));
|
||||
} else {
|
||||
nodeInfo.feeDelta[endPeriod] += int256(policy.feeRate);
|
||||
nodeInfo.feeDelta[endPeriod] += int256(uint256(policy.feeRate));
|
||||
}
|
||||
|
||||
// Reset to default value if needed
|
||||
|
@ -612,7 +612,7 @@ contract PolicyManager is Upgradeable {
|
|||
if (numberOfActive == 0) {
|
||||
policy.disabled = true;
|
||||
// gas refund
|
||||
policy.sponsor = address(0);
|
||||
policy.sponsor = payable(address(0));
|
||||
policy.owner = address(0);
|
||||
policy.feeRate = 0;
|
||||
policy.startTimestamp = 0;
|
||||
|
@ -688,7 +688,7 @@ contract PolicyManager is Upgradeable {
|
|||
* @return Revocation hash, EIP191 version 0x45 ('E')
|
||||
*/
|
||||
function getRevocationHash(bytes16 _policyId, address _node) public view returns (bytes32) {
|
||||
return SignatureVerifier.hashEIP191(abi.encodePacked(_policyId, _node), byte(0x45));
|
||||
return SignatureVerifier.hashEIP191(abi.encodePacked(_policyId, _node), bytes1(0x45));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -832,7 +832,7 @@ contract PolicyManager is Upgradeable {
|
|||
function delegateGetNodeInfo(address _target, address _node)
|
||||
internal returns (MemoryNodeInfo memory result)
|
||||
{
|
||||
bytes32 memoryAddress = delegateGetData(_target, this.nodes.selector, 1, bytes32(uint256(_node)), 0);
|
||||
bytes32 memoryAddress = delegateGetData(_target, this.nodes.selector, 1, bytes32(uint256(uint160(_node))), 0);
|
||||
assembly {
|
||||
result := memoryAddress
|
||||
}
|
||||
|
@ -899,7 +899,7 @@ contract PolicyManager is Upgradeable {
|
|||
|
||||
// Create fake Policy and NodeInfo to use them in verifyState(address)
|
||||
Policy storage policy = policies[RESERVED_POLICY_ID];
|
||||
policy.sponsor = msg.sender;
|
||||
policy.sponsor = payable(msg.sender);
|
||||
policy.owner = address(this);
|
||||
policy.startTimestamp = 1;
|
||||
policy.endTimestamp = 2;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "aragon/interfaces/IERC900History.sol";
|
||||
|
@ -10,6 +10,7 @@ import "contracts/lib/Snapshot.sol";
|
|||
import "contracts/proxy/Upgradeable.sol";
|
||||
import "zeppelin/math/Math.sol";
|
||||
import "zeppelin/token/ERC20/SafeERC20.sol";
|
||||
import "threshold/IStaking.sol";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -57,7 +58,7 @@ contract StakingEscrowStub is Upgradeable {
|
|||
super.verifyState(_testTarget);
|
||||
|
||||
// we have to use real values even though this is a stub
|
||||
require(address(delegateGet(_testTarget, this.token.selector)) == address(token));
|
||||
require(address(uint160(delegateGet(_testTarget, this.token.selector))) == address(token));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,12 +67,11 @@ contract StakingEscrowStub is Upgradeable {
|
|||
* @title StakingEscrow
|
||||
* @notice Contract holds and locks stakers tokens.
|
||||
* Each staker that locks their tokens will receive some compensation
|
||||
* @dev |v6.1.1|
|
||||
* @dev |v6.2.1|
|
||||
*/
|
||||
contract StakingEscrow is Upgradeable, IERC900History {
|
||||
|
||||
using Bits for uint256;
|
||||
using SafeMath for uint256;
|
||||
using Snapshot for uint128[];
|
||||
using SafeERC20 for NuCypherToken;
|
||||
|
||||
|
@ -98,80 +98,100 @@ contract StakingEscrow is Upgradeable, IERC900History {
|
|||
*/
|
||||
event Slashed(address indexed staker, uint256 penalty, address indexed investigator, uint256 reward);
|
||||
|
||||
struct SubStakeInfo {
|
||||
uint16 firstPeriod;
|
||||
uint16 lastPeriod;
|
||||
uint16 unlockingDuration;
|
||||
uint128 lockedValue;
|
||||
}
|
||||
/**
|
||||
* @notice Signals that vesting parameters were set for the staker
|
||||
* @param staker Staker address
|
||||
* @param releaseTimestamp Release timestamp
|
||||
* @param releaseRate Release rate
|
||||
*/
|
||||
event VestingSet(address indexed staker, uint256 releaseTimestamp, uint256 releaseRate);
|
||||
|
||||
struct Downtime {
|
||||
uint16 startPeriod;
|
||||
uint16 endPeriod;
|
||||
}
|
||||
/**
|
||||
* @notice Signals that the staker requested merge with T staking contract
|
||||
* @param staker Staker address
|
||||
* @param operator Operator address
|
||||
*/
|
||||
event MergeRequested(address indexed staker, address indexed operator);
|
||||
|
||||
/**
|
||||
* @notice Signals that the staker confirmed merge with T staking contract
|
||||
* @param staker Staker address
|
||||
*/
|
||||
event MergeConfirmed(address indexed staker);
|
||||
|
||||
struct StakerInfo {
|
||||
uint256 value;
|
||||
uint16 currentCommittedPeriod;
|
||||
uint16 nextCommittedPeriod;
|
||||
uint16 lastCommittedPeriod;
|
||||
uint16 stub1; // former slot for lockReStakeUntilPeriod
|
||||
uint256 completedWork;
|
||||
uint16 workerStartPeriod; // period when worker was bonded
|
||||
address worker;
|
||||
|
||||
uint16 stub1; // former slot for currentCommittedPeriod // TODO combine slots?
|
||||
uint16 stub2; // former slot for nextCommittedPeriod
|
||||
uint16 lastCommittedPeriod; // used only in depositFromWorkLock
|
||||
uint16 stub4; // former slot for lockReStakeUntilPeriod
|
||||
uint256 stub5; // former slot for completedWork
|
||||
uint16 stub6; // former slot for workerStartPeriod
|
||||
address stub7; // former slot for worker
|
||||
|
||||
uint256 flags; // uint256 to acquire whole slot and minimize operations on it
|
||||
|
||||
uint256 reservedSlot1;
|
||||
uint256 reservedSlot2;
|
||||
uint256 reservedSlot3;
|
||||
uint256 vestingReleaseTimestamp;
|
||||
uint256 vestingReleaseRate;
|
||||
address operator;
|
||||
|
||||
uint256 reservedSlot4;
|
||||
uint256 reservedSlot5;
|
||||
|
||||
Downtime[] pastDowntime;
|
||||
SubStakeInfo[] subStakes;
|
||||
uint128[] history;
|
||||
uint256[] stub8; // former slot for pastDowntime
|
||||
uint256[] stub9; // former slot for subStakes
|
||||
uint128[] history; // TODO keep or remove?
|
||||
|
||||
}
|
||||
|
||||
// indices for flags (0-4 were in use, skip it in future)
|
||||
// uint8 internal constant SNAPSHOTS_DISABLED_INDEX = 3;
|
||||
uint8 internal constant MERGED_INDEX = 5;
|
||||
|
||||
uint256 internal constant ACCEPTABLE_STAKING_ERROR = 10**15;
|
||||
|
||||
NuCypherToken public immutable token;
|
||||
WorkLockInterface public immutable workLock;
|
||||
IStaking public immutable tStaking;
|
||||
|
||||
uint128 public previousPeriodSupply; // outdated
|
||||
uint128 public currentPeriodSupply; // outdated
|
||||
uint16 public currentMintingPeriod; // outdated
|
||||
uint128 private stub1; // former slot for previousPeriodSupply
|
||||
uint128 public currentPeriodSupply; // resulting token supply
|
||||
uint16 private stub2; // former slot for currentMintingPeriod
|
||||
|
||||
mapping (address => StakerInfo) public stakerInfo;
|
||||
address[] public stakers;
|
||||
mapping (address => address) public stakerFromWorker; // outdated
|
||||
mapping (address => address) private stub3; // former slot for stakerFromWorker
|
||||
|
||||
mapping (uint16 => uint256) stub1; // former slot for lockedPerPeriod
|
||||
mapping (uint16 => uint256) private stub4; // former slot for lockedPerPeriod
|
||||
uint128[] public balanceHistory; // outdated
|
||||
|
||||
address stub2; // former slot for PolicyManager
|
||||
address stub3; // former slot for Adjudicator
|
||||
address stub4; // former slot for WorkLock
|
||||
address private stub5; // former slot for PolicyManager
|
||||
address private stub6; // former slot for Adjudicator
|
||||
address private stub7; // former slot for WorkLock
|
||||
|
||||
mapping (uint16 => uint256) public lockedPerPeriod; // outdated
|
||||
mapping (uint16 => uint256) private stub8; // last former slot for lockedPerPeriod
|
||||
|
||||
/**
|
||||
* @notice Constructor sets address of token contract and parameters for staking
|
||||
* @param _token NuCypher token contract
|
||||
* @param _workLock WorkLock contract. Zero address if there is no WorkLock
|
||||
* @param _tStaking T token staking contract
|
||||
*/
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
WorkLockInterface _workLock
|
||||
WorkLockInterface _workLock,
|
||||
IStaking _tStaking
|
||||
) {
|
||||
require(_token.totalSupply() > 0 &&
|
||||
_tStaking.stakedNu(address(0)) == 0 &&
|
||||
(address(_workLock) == address(0) || _workLock.token() == _token),
|
||||
"Input addresses must be deployed contracts"
|
||||
);
|
||||
|
||||
token = _token;
|
||||
workLock = _workLock;
|
||||
tStaking = _tStaking;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -183,6 +203,15 @@ contract StakingEscrow is Upgradeable, IERC900History {
|
|||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks caller is T staking contract
|
||||
*/
|
||||
modifier onlyTStakingContract()
|
||||
{
|
||||
require(msg.sender == address(tStaking), "Caller must be the T staking contract");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks caller is WorkLock contract
|
||||
*/
|
||||
|
@ -200,17 +229,17 @@ contract StakingEscrow is Upgradeable, IERC900History {
|
|||
return stakerInfo[_staker].value;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @notice Get all flags for the staker
|
||||
// */
|
||||
// function getFlags(address _staker)
|
||||
// external view returns (
|
||||
// bool snapshots
|
||||
// )
|
||||
// {
|
||||
// StakerInfo storage info = stakerInfo[_staker];
|
||||
// snapshots = !info.flags.bitSet(SNAPSHOTS_DISABLED_INDEX);
|
||||
// }
|
||||
/**
|
||||
* @notice Get all flags for the staker
|
||||
*/
|
||||
function getFlags(address _staker)
|
||||
external view returns (
|
||||
bool merged
|
||||
)
|
||||
{
|
||||
StakerInfo storage info = stakerInfo[_staker];
|
||||
merged = info.flags.bitSet(MERGED_INDEX);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get work that completed by the staker
|
||||
|
@ -258,6 +287,105 @@ contract StakingEscrow is Upgradeable, IERC900History {
|
|||
emit Deposited(_staker, _value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Withdraw available amount of NU tokens to staker
|
||||
* @param _value Amount of tokens to withdraw
|
||||
*/
|
||||
function withdraw(uint256 _value) external onlyStaker {
|
||||
StakerInfo storage info = stakerInfo[msg.sender];
|
||||
require(info.flags.bitSet(MERGED_INDEX), "Merge must be confirmed");
|
||||
require(
|
||||
_value + tStaking.stakedNu(info.operator) <= info.value,
|
||||
"Not enough tokens unstaked in T staking contract"
|
||||
);
|
||||
require(
|
||||
_value + getVestedTokens(msg.sender) <= info.value,
|
||||
"Not enough tokens released during vesting"
|
||||
);
|
||||
info.value -= _value;
|
||||
|
||||
addSnapshot(info, - int256(_value));
|
||||
token.safeTransfer(msg.sender, _value);
|
||||
emit Withdrawn(msg.sender, _value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Returns amount of not released yet tokens for staker
|
||||
*/
|
||||
function getVestedTokens(address _staker) public view returns (uint256) {
|
||||
StakerInfo storage info = stakerInfo[_staker];
|
||||
if (info.vestingReleaseTimestamp <= block.timestamp) {
|
||||
return 0;
|
||||
}
|
||||
return (block.timestamp - info.vestingReleaseTimestamp) * info.vestingReleaseRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Setup vesting parameters
|
||||
* @param _stakers Array of stakers
|
||||
* @param _releaseTimestamp Array of timestamps when stake will be released
|
||||
* @param _releaseRate Array of release rates
|
||||
*/
|
||||
function setupVesting(
|
||||
address[] calldata _stakers,
|
||||
uint256[] calldata _releaseTimestamp,
|
||||
uint256[] calldata _releaseRate
|
||||
) external onlyOwner {
|
||||
require(_stakers.length == _releaseTimestamp.length &&
|
||||
_releaseTimestamp.length == _releaseRate.length,
|
||||
"Input arrays must have same number of elements"
|
||||
);
|
||||
for (uint256 i = 0; i < _stakers.length; i++) {
|
||||
address staker = _stakers[i];
|
||||
StakerInfo storage info = stakerInfo[staker];
|
||||
require(info.vestingReleaseTimestamp == 0, "Vesting parameters can be set only once");
|
||||
info.vestingReleaseTimestamp = _releaseTimestamp[i];
|
||||
info.vestingReleaseRate = _releaseRate[i];
|
||||
require(getVestedTokens(staker) > 0, "Vesting parameters must be set properly");
|
||||
emit VestingSet(staker, info.vestingReleaseTimestamp, info.vestingReleaseRate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Request migration to threshold network
|
||||
* @param _staker Staker address
|
||||
* @param _operator Operator address
|
||||
* @return Amount of tokens
|
||||
*/
|
||||
function requestMerge(address _staker, address _operator)
|
||||
external onlyTStakingContract returns (uint256)
|
||||
{
|
||||
StakerInfo storage info = stakerInfo[_staker];
|
||||
require(
|
||||
info.operator == address(0) || info.operator == _operator,
|
||||
"Operator already set for the staker"
|
||||
);
|
||||
if (info.operator == address(0)) {
|
||||
info.operator = _operator;
|
||||
emit MergeRequested(_staker, _operator);
|
||||
}
|
||||
return info.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Confirm migration to threshold network
|
||||
* @param _staker Staker address
|
||||
*/
|
||||
function confirmMerge(address _staker) external {
|
||||
StakerInfo storage info = stakerInfo[_staker];
|
||||
require(info.operator != address(0), "Staker didn't request merge");
|
||||
|
||||
require(!info.flags.bitSet(MERGED_INDEX), "Merge already confirmed");
|
||||
uint256 stakedNu = tStaking.stakedNu(info.operator);
|
||||
require(stakedNu + ACCEPTABLE_STAKING_ERROR >= info.value, "All tokens must be staked");
|
||||
|
||||
uint96 minStakedNuInT = tStaking.getMinStaked(info.operator, IStaking.StakeType.NU);
|
||||
(,, uint96 stakedNuInT) = tStaking.stakes(info.operator);
|
||||
require(minStakedNuInT == stakedNuInT, "All tokens must be authorized");
|
||||
info.flags = info.flags.toggleBit(MERGED_INDEX);
|
||||
emit MergeConfirmed(_staker);
|
||||
}
|
||||
|
||||
//-------------------------Slashing-------------------------
|
||||
/**
|
||||
* @notice Slash the staker's stake and reward the investigator
|
||||
|
@ -272,7 +400,7 @@ contract StakingEscrow is Upgradeable, IERC900History {
|
|||
address _investigator,
|
||||
uint256 _reward
|
||||
)
|
||||
internal
|
||||
external onlyTStakingContract
|
||||
{
|
||||
require(_penalty > 0, "Penalty must be specified");
|
||||
StakerInfo storage info = stakerInfo[_staker];
|
||||
|
@ -298,54 +426,6 @@ contract StakingEscrow is Upgradeable, IERC900History {
|
|||
return stakers.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Return the length of the array of sub stakes
|
||||
*/
|
||||
function getSubStakesLength(address _staker) external view returns (uint256) {
|
||||
return stakerInfo[_staker].subStakes.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Return the information about sub stake
|
||||
*/
|
||||
function getSubStakeInfo(address _staker, uint256 _index)
|
||||
// TODO change to structure when ABIEncoderV2 is released (#1501)
|
||||
// public view returns (SubStakeInfo)
|
||||
// TODO "virtual" only for tests, probably will be removed after #1512
|
||||
external view virtual returns (
|
||||
uint16 firstPeriod,
|
||||
uint16 lastPeriod,
|
||||
uint16 unlockingDuration,
|
||||
uint128 lockedValue
|
||||
)
|
||||
{
|
||||
SubStakeInfo storage info = stakerInfo[_staker].subStakes[_index];
|
||||
firstPeriod = info.firstPeriod;
|
||||
lastPeriod = info.lastPeriod;
|
||||
unlockingDuration = info.unlockingDuration;
|
||||
lockedValue = info.lockedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Return the length of the array of past downtime
|
||||
*/
|
||||
function getPastDowntimeLength(address _staker) external view returns (uint256) {
|
||||
return stakerInfo[_staker].pastDowntime.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Return the information about past downtime
|
||||
*/
|
||||
function getPastDowntime(address _staker, uint256 _index)
|
||||
// TODO change to structure when ABIEncoderV2 is released (#1501)
|
||||
// public view returns (Downtime)
|
||||
external view returns (uint16 startPeriod, uint16 endPeriod)
|
||||
{
|
||||
Downtime storage downtime = stakerInfo[_staker].pastDowntime[_index];
|
||||
startPeriod = downtime.startPeriod;
|
||||
endPeriod = downtime.endPeriod;
|
||||
}
|
||||
|
||||
//------------------ ERC900 connectors ----------------------
|
||||
|
||||
function totalStakedForAt(address _owner, uint256 _blockNumber) public view override returns (uint256) {
|
||||
|
@ -390,10 +470,12 @@ contract StakingEscrow is Upgradeable, IERC900History {
|
|||
address stakerAddress = stakers[0];
|
||||
require(address(uint160(delegateGet(_testTarget, this.stakers.selector, 0))) == stakerAddress);
|
||||
StakerInfo storage info = stakerInfo[stakerAddress];
|
||||
bytes32 staker = bytes32(uint256(stakerAddress));
|
||||
bytes32 staker = bytes32(uint256(uint160(stakerAddress)));
|
||||
StakerInfo memory infoToCheck = delegateGetStakerInfo(_testTarget, staker);
|
||||
require(
|
||||
infoToCheck.value == info.value &&
|
||||
require(infoToCheck.value == info.value &&
|
||||
infoToCheck.vestingReleaseTimestamp == info.vestingReleaseTimestamp &&
|
||||
infoToCheck.vestingReleaseRate == info.vestingReleaseRate &&
|
||||
infoToCheck.operator == info.operator &&
|
||||
infoToCheck.flags == info.flags
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0; // TODO use 0.7.x version and revert changes ?
|
||||
|
||||
|
||||
import "zeppelin/math/SafeMath.sol";
|
||||
|
@ -335,7 +335,7 @@ contract WorkLock is Ownable {
|
|||
if (refundETH > minAllowedBid) {
|
||||
bonusETHSupply = bonusETHSupply.sub(refundETH - minAllowedBid);
|
||||
}
|
||||
msg.sender.sendValue(refundETH);
|
||||
payable(msg.sender).sendValue(refundETH);
|
||||
emit Canceled(msg.sender, refundETH);
|
||||
}
|
||||
|
||||
|
@ -444,7 +444,7 @@ contract WorkLock is Ownable {
|
|||
uint256 refund = compensation[msg.sender];
|
||||
require(refund > 0, "There is no compensation");
|
||||
compensation[msg.sender] = 0;
|
||||
msg.sender.sendValue(refund);
|
||||
payable(msg.sender).sendValue(refund);
|
||||
emit CompensationWithdrawn(msg.sender, refund);
|
||||
}
|
||||
|
||||
|
@ -550,6 +550,6 @@ contract WorkLock is Ownable {
|
|||
|
||||
info.completedWork = info.completedWork.add(completedWork);
|
||||
emit Refund(msg.sender, refundETH, completedWork);
|
||||
msg.sender.sendValue(refundETH);
|
||||
payable(msg.sender).sendValue(refundETH);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
interface IForwarder {
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
interface TokenManager {
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "contracts/dao/IForwarder.sol";
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "zeppelin/math/SafeMath.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Taken from https://github.com/ethereum/solidity-examples/blob/master/src/bits/Bits.sol
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "contracts/lib/UmbralDeserializer.sol";
|
||||
import "contracts/lib/SignatureVerifier.sol";
|
||||
|
@ -385,7 +385,7 @@ library ReEncryptionValidator {
|
|||
) internal pure returns(bool) {
|
||||
uint256 curve_order = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
|
||||
address signer = ecrecover(0, uint8(27 + (y1 % 2)), bytes32(x1), bytes32(mulmod(scalar, x1, curve_order)));
|
||||
address xyAddress = address(uint256(keccak256(abi.encodePacked(qx, qy))) & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
|
||||
address xyAddress = address(uint160(uint256(keccak256(abi.encodePacked(qx, qy))) & 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF));
|
||||
return xyAddress == signer;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -101,16 +101,16 @@ library SignatureVerifier {
|
|||
*/
|
||||
function hashEIP191(
|
||||
bytes memory _message,
|
||||
byte _version
|
||||
bytes1 _version
|
||||
)
|
||||
internal
|
||||
view
|
||||
returns (bytes32 result)
|
||||
{
|
||||
if(_version == byte(0x00)){ // Version 0: Data with intended validator
|
||||
if(_version == bytes1(0x00)){ // Version 0: Data with intended validator
|
||||
address validator = address(this);
|
||||
return keccak256(abi.encodePacked(byte(0x19), byte(0x00), validator, _message));
|
||||
} else if (_version == byte(0x45)){ // Version E: personal_sign messages
|
||||
return keccak256(abi.encodePacked(bytes1(0x19), bytes1(0x00), validator, _message));
|
||||
} else if (_version == bytes1(0x45)){ // Version E: personal_sign messages
|
||||
uint256 length = _message.length;
|
||||
require(length > 0, "Empty message not allowed for version E");
|
||||
|
||||
|
@ -124,11 +124,11 @@ library SignatureVerifier {
|
|||
length = _message.length;
|
||||
uint256 index = digits - 1;
|
||||
while (length != 0) {
|
||||
lengthAsText[index--] = byte(uint8(48 + length % 10));
|
||||
lengthAsText[index--] = bytes1(uint8(48 + length % 10));
|
||||
length /= 10;
|
||||
}
|
||||
|
||||
return keccak256(abi.encodePacked(byte(0x19), EIP191_VERSION_E_HEADER, lengthAsText, _message));
|
||||
return keccak256(abi.encodePacked(bytes1(0x19), EIP191_VERSION_E_HEADER, lengthAsText, _message));
|
||||
} else {
|
||||
revert("Unsupported EIP191 version");
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ library SignatureVerifier {
|
|||
bytes memory _message,
|
||||
bytes memory _signature,
|
||||
bytes memory _publicKey,
|
||||
byte _version
|
||||
bytes1 _version
|
||||
)
|
||||
internal
|
||||
view
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -259,7 +259,7 @@ library UmbralDeserializer {
|
|||
/**
|
||||
* @notice Read 1 byte from memory in the pointer position
|
||||
*/
|
||||
function getByte(uint256 _pointer) internal pure returns (byte result) {
|
||||
function getByte(uint256 _pointer) internal pure returns (bytes1 result) {
|
||||
bytes32 word;
|
||||
assembly {
|
||||
word := mload(_pointer)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "./Upgradeable.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "zeppelin/ownership/Ownable.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "zeppelin/ownership/Ownable.sol";
|
||||
import "zeppelin/utils/Address.sol";
|
||||
|
|
|
@ -1,16 +1,14 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "zeppelin/ownership/Ownable.sol";
|
||||
import "zeppelin/math/SafeMath.sol";
|
||||
import "contracts/staking_contracts/AbstractStakingContract.sol";
|
||||
|
||||
/**
|
||||
* @notice Contract acts as delegate for sub-stakers
|
||||
**/
|
||||
contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
||||
using SafeMath for uint256;
|
||||
using Address for address payable;
|
||||
using SafeERC20 for NuCypherToken;
|
||||
|
||||
|
@ -115,9 +113,9 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
function depositTokens(uint256 _value) external {
|
||||
require(isDepositAllowed(), "Deposit must be enabled");
|
||||
require(_value > 0, "Value must be not empty");
|
||||
totalDepositedTokens = totalDepositedTokens.add(_value);
|
||||
totalDepositedTokens += _value;
|
||||
Delegator storage delegator = delegators[msg.sender];
|
||||
delegator.depositedTokens = delegator.depositedTokens.add(_value);
|
||||
delegator.depositedTokens += _value;
|
||||
token.safeTransferFrom(msg.sender, address(this), _value);
|
||||
emit TokensDeposited(msg.sender, _value, delegator.depositedTokens);
|
||||
}
|
||||
|
@ -131,7 +129,7 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
// tokens which directly belong to pool
|
||||
uint256 freeTokens = token.balanceOf(address(this));
|
||||
// tokens in excess of the initially deposited
|
||||
uint256 reward = stakedTokens.add(freeTokens).sub(totalDepositedTokens);
|
||||
uint256 reward = stakedTokens + freeTokens - totalDepositedTokens;
|
||||
// check how many of reward tokens belong directly to pool
|
||||
if (reward > freeTokens) {
|
||||
return freeTokens;
|
||||
|
@ -144,7 +142,7 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
* Available and withdrawn reward together to use in delegator/owner reward calculations
|
||||
*/
|
||||
function getCumulativeReward() public view returns (uint256) {
|
||||
return getAvailableReward().add(totalWithdrawnReward);
|
||||
return getAvailableReward() + totalWithdrawnReward;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -159,7 +157,7 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
// usual case
|
||||
if (totalDepositedTokens != 0) {
|
||||
uint256 fraction = getWorkerFraction();
|
||||
maxAllowableReward = reward.mul(fraction).div(BASIS_FRACTION);
|
||||
maxAllowableReward = reward * fraction / BASIS_FRACTION;
|
||||
// special case when there are no delegators
|
||||
} else {
|
||||
maxAllowableReward = reward;
|
||||
|
@ -188,9 +186,8 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
|
||||
// calculate total reward for delegator including historical reward
|
||||
// excluding worker share
|
||||
uint256 maxAllowableReward = reward.mul(delegator.depositedTokens).mul(BASIS_FRACTION - fraction).div(
|
||||
totalDepositedTokens.mul(BASIS_FRACTION)
|
||||
);
|
||||
uint256 maxAllowableReward = reward * delegator.depositedTokens * (BASIS_FRACTION - fraction)
|
||||
/ (totalDepositedTokens * BASIS_FRACTION);
|
||||
|
||||
// check that worker has any new reward
|
||||
if (maxAllowableReward > delegator.withdrawnReward) {
|
||||
|
@ -214,8 +211,8 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
availableReward > 0,
|
||||
"There is no available reward to withdraw"
|
||||
);
|
||||
workerWithdrawnReward = workerWithdrawnReward.add(availableReward);
|
||||
totalWithdrawnReward = totalWithdrawnReward.add(availableReward);
|
||||
workerWithdrawnReward += availableReward;
|
||||
totalWithdrawnReward += availableReward;
|
||||
|
||||
token.safeTransfer(msg.sender, availableReward);
|
||||
emit TokensWithdrawn(msg.sender, availableReward, 0);
|
||||
|
@ -233,8 +230,8 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
uint256 availableReward = getAvailableDelegatorReward(msg.sender);
|
||||
|
||||
require( _value <= availableReward, "Requested amount of tokens exceeded allowed portion");
|
||||
delegator.withdrawnReward = delegator.withdrawnReward.add(_value);
|
||||
totalWithdrawnReward = totalWithdrawnReward.add(_value);
|
||||
delegator.withdrawnReward += _value;
|
||||
totalWithdrawnReward += _value;
|
||||
|
||||
token.safeTransfer(msg.sender, _value);
|
||||
emit TokensWithdrawn(msg.sender, _value, delegator.depositedTokens);
|
||||
|
@ -249,7 +246,7 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
|
||||
Delegator storage delegator = delegators[msg.sender];
|
||||
uint256 availableReward = getAvailableDelegatorReward(msg.sender);
|
||||
uint256 value = availableReward.add(delegator.depositedTokens);
|
||||
uint256 value = availableReward + delegator.depositedTokens;
|
||||
require(value <= balance, "Not enough tokens in the contract");
|
||||
|
||||
// TODO remove double reading: availableReward and availableWorkerReward use same calls to external contracts
|
||||
|
@ -259,18 +256,18 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
uint256 availableETH = getAvailableDelegatorETH(msg.sender);
|
||||
|
||||
// prevent losing reward for worker after calculations
|
||||
uint256 workerReward = availableWorkerReward.mul(delegator.depositedTokens).div(totalDepositedTokens);
|
||||
uint256 workerReward = availableWorkerReward * delegator.depositedTokens / totalDepositedTokens;
|
||||
if (workerReward > 0) {
|
||||
require(value.add(workerReward) <= balance, "Not enough tokens in the contract");
|
||||
require(value + workerReward <= balance, "Not enough tokens in the contract");
|
||||
token.safeTransfer(workerOwner, workerReward);
|
||||
emit TokensWithdrawn(workerOwner, workerReward, 0);
|
||||
}
|
||||
|
||||
uint256 withdrawnToDecrease = workerWithdrawnReward.mul(delegator.depositedTokens).div(totalDepositedTokens);
|
||||
uint256 withdrawnToDecrease = workerWithdrawnReward * delegator.depositedTokens / totalDepositedTokens;
|
||||
|
||||
workerWithdrawnReward = workerWithdrawnReward.sub(withdrawnToDecrease);
|
||||
totalWithdrawnReward = totalWithdrawnReward.sub(withdrawnToDecrease).sub(delegator.withdrawnReward);
|
||||
totalDepositedTokens = totalDepositedTokens.sub(delegator.depositedTokens);
|
||||
workerWithdrawnReward -= withdrawnToDecrease;
|
||||
totalWithdrawnReward -= withdrawnToDecrease + delegator.withdrawnReward;
|
||||
totalDepositedTokens -= delegator.depositedTokens;
|
||||
|
||||
delegator.withdrawnReward = 0;
|
||||
delegator.depositedTokens = 0;
|
||||
|
@ -278,11 +275,11 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
token.safeTransfer(msg.sender, value);
|
||||
emit TokensWithdrawn(msg.sender, value, 0);
|
||||
|
||||
totalWithdrawnETH = totalWithdrawnETH.sub(delegator.withdrawnETH);
|
||||
totalWithdrawnETH -= delegator.withdrawnETH;
|
||||
delegator.withdrawnETH = 0;
|
||||
if (availableETH > 0) {
|
||||
emit ETHWithdrawn(msg.sender, availableETH);
|
||||
msg.sender.sendValue(availableETH);
|
||||
payable(msg.sender).sendValue(availableETH);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,10 +290,10 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
Delegator storage delegator = delegators[_delegator];
|
||||
uint256 balance = address(this).balance;
|
||||
// ETH balance + already withdrawn
|
||||
balance = balance.add(totalWithdrawnETH);
|
||||
uint256 maxAllowableETH = balance.mul(delegator.depositedTokens).div(totalDepositedTokens);
|
||||
balance += totalWithdrawnETH;
|
||||
uint256 maxAllowableETH = balance * delegator.depositedTokens / totalDepositedTokens;
|
||||
|
||||
uint256 availableETH = maxAllowableETH.sub(delegator.withdrawnETH);
|
||||
uint256 availableETH = maxAllowableETH - delegator.withdrawnETH;
|
||||
if (availableETH > balance) {
|
||||
availableETH = balance;
|
||||
}
|
||||
|
@ -310,11 +307,11 @@ contract PoolingStakingContractV2 is InitializableStakingContract, Ownable {
|
|||
Delegator storage delegator = delegators[msg.sender];
|
||||
uint256 availableETH = getAvailableDelegatorETH(msg.sender);
|
||||
require(availableETH > 0, "There is no available ETH to withdraw");
|
||||
delegator.withdrawnETH = delegator.withdrawnETH.add(availableETH);
|
||||
delegator.withdrawnETH += availableETH;
|
||||
|
||||
totalWithdrawnETH = totalWithdrawnETH.add(availableETH);
|
||||
totalWithdrawnETH += availableETH;
|
||||
emit ETHWithdrawn(msg.sender, availableETH);
|
||||
msg.sender.sendValue(availableETH);
|
||||
payable(msg.sender).sendValue(availableETH);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/staking_contracts/AbstractStakingContract.sol";
|
||||
|
|
|
@ -0,0 +1,358 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
/// @title Interface of Threshold Network staking contract
|
||||
/// @notice The staking contract enables T owners to have their wallets offline
|
||||
/// and their stake operated by operators on their behalf. All off-chain
|
||||
/// client software should be able to run without exposing operator’s
|
||||
/// private key and should not require any owner’s keys at all.
|
||||
/// The stake delegation optimizes the network throughput without
|
||||
/// compromising the security of the owners’ stake.
|
||||
interface IStaking {
|
||||
enum StakeType {
|
||||
NU,
|
||||
KEEP,
|
||||
T
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// Delegating a stake
|
||||
//
|
||||
//
|
||||
|
||||
/// @notice Creates a delegation with `msg.sender` owner with the given
|
||||
/// operator, beneficiary, and authorizer. Transfers the given
|
||||
/// amount of T to the staking contract.
|
||||
/// @dev The owner of the delegation needs to have the amount approved to
|
||||
/// transfer to the staking contract.
|
||||
function stake(
|
||||
address operator,
|
||||
address payable beneficiary,
|
||||
address authorizer,
|
||||
uint96 amount
|
||||
) external;
|
||||
|
||||
/// @notice Copies delegation from the legacy KEEP staking contract to T
|
||||
/// staking contract. No tokens are transferred. Caches the active
|
||||
/// stake amount from KEEP staking contract. Can be called by
|
||||
/// anyone.
|
||||
function stakeKeep(address operator) external;
|
||||
|
||||
/// @notice Copies delegation from the legacy NU staking contract to T
|
||||
/// staking contract, additionally appointing beneficiary and
|
||||
/// authorizer roles. Caches the amount staked in NU staking
|
||||
/// contract. Can be called only by the original delegation owner.
|
||||
function stakeNu(
|
||||
address operator,
|
||||
address payable beneficiary,
|
||||
address authorizer
|
||||
) external;
|
||||
|
||||
/// @notice Refresh Keep stake owner. Can be called only by the old owner.
|
||||
function refreshKeepStakeOwner(address operator) external;
|
||||
|
||||
/// @notice Allows the Governance to set the minimum required stake amount.
|
||||
/// This amount is required to protect against griefing the staking
|
||||
/// contract and individual applications are allowed to require
|
||||
/// higher minimum stakes if necessary.
|
||||
function setMinimumStakeAmount(uint96 amount) external;
|
||||
|
||||
//
|
||||
//
|
||||
// Authorizing an application
|
||||
//
|
||||
//
|
||||
|
||||
/// @notice Allows the Governance to approve the particular application
|
||||
/// before individual stake authorizers are able to authorize it.
|
||||
function approveApplication(address application) external;
|
||||
|
||||
/// @notice Increases the authorization of the given operator for the given
|
||||
/// application by the given amount. Can only be called by the given
|
||||
/// operator’s authorizer.
|
||||
/// @dev Calls `authorizationIncreased(address operator, uint256 amount)`
|
||||
/// on the given application to notify the application about
|
||||
/// authorization change. See `IApplication`.
|
||||
function increaseAuthorization(
|
||||
address operator,
|
||||
address application,
|
||||
uint96 amount
|
||||
) external;
|
||||
|
||||
/// @notice Requests decrease of the authorization for the given operator on
|
||||
/// the given application by the provided amount.
|
||||
/// It may not change the authorized amount immediatelly. When
|
||||
/// it happens depends on the application. Can only be called by the
|
||||
/// given operator’s authorizer. Overwrites pending authorization
|
||||
/// decrease for the given operator and application.
|
||||
/// @dev Calls `authorizationDecreaseRequested(address operator, uint256 amount)`
|
||||
/// on the given application. See `IApplication`.
|
||||
function requestAuthorizationDecrease(
|
||||
address operator,
|
||||
address application,
|
||||
uint96 amount
|
||||
) external;
|
||||
|
||||
/// @notice Requests decrease of all authorizations for the given operator on
|
||||
/// the applications by all authorized amount.
|
||||
/// It may not change the authorized amount immediatelly. When
|
||||
/// it happens depends on the application. Can only be called by the
|
||||
/// given operator’s authorizer. Overwrites pending authorization
|
||||
/// decrease for the given operator and application.
|
||||
/// @dev Calls `authorizationDecreaseRequested(address operator, uint256 amount)`
|
||||
/// for each authorized application. See `IApplication`.
|
||||
function requestAuthorizationDecrease(address operator) external;
|
||||
|
||||
/// @notice Called by the application at its discretion to approve the
|
||||
/// previously requested authorization decrease request. Can only be
|
||||
/// called by the application that was previously requested to
|
||||
/// decrease the authorization for that operator.
|
||||
/// Returns resulting authorized amount for the application.
|
||||
function approveAuthorizationDecrease(address operator)
|
||||
external
|
||||
returns (uint96);
|
||||
|
||||
/// @notice Decreases the authorization for the given `operator` on
|
||||
/// the given disabled `application`, for all authorized amount.
|
||||
/// Can be called by anyone.
|
||||
function forceDecreaseAuthorization(address operator, address application)
|
||||
external;
|
||||
|
||||
/// @notice Pauses the given application’s eligibility to slash stakes.
|
||||
/// Besides that stakers can't change authorization to the application.
|
||||
/// Can be called only by the Panic Button of the particular
|
||||
/// application. The paused application can not slash stakes until
|
||||
/// it is approved again by the Governance using `approveApplication`
|
||||
/// function. Should be used only in case of an emergency.
|
||||
function pauseApplication(address application) external;
|
||||
|
||||
/// @notice Disables the given application. The disabled application can't
|
||||
/// slash stakers. Also stakers can't increase authorization to that
|
||||
/// application but can decrease without waiting by calling
|
||||
/// `requestAuthorizationDecrease` at any moment. Can be called only
|
||||
/// by the governance. The disabled application can't be approved
|
||||
/// again. Should be used only in case of an emergency.
|
||||
function disableApplication(address application) external;
|
||||
|
||||
/// @notice Sets the Panic Button role for the given application to the
|
||||
/// provided address. Can only be called by the Governance. If the
|
||||
/// Panic Button for the given application should be disabled, the
|
||||
/// role address should be set to 0x0 address.
|
||||
function setPanicButton(address application, address panicButton) external;
|
||||
|
||||
/// @notice Sets the maximum number of applications one operator can
|
||||
/// authorize. Used to protect against DoSing slashing queue.
|
||||
/// Can only be called by the Governance.
|
||||
function setAuthorizationCeiling(uint256 ceiling) external;
|
||||
|
||||
//
|
||||
//
|
||||
// Stake top-up
|
||||
//
|
||||
//
|
||||
|
||||
/// @notice Increases the amount of the stake for the given operator.
|
||||
/// Can be called only by the owner or operator.
|
||||
/// @dev The sender of this transaction needs to have the amount approved to
|
||||
/// transfer to the staking contract.
|
||||
function topUp(address operator, uint96 amount) external;
|
||||
|
||||
/// @notice Propagates information about stake top-up from the legacy KEEP
|
||||
/// staking contract to T staking contract. Can be called only by
|
||||
/// the owner or operator.
|
||||
function topUpKeep(address operator) external;
|
||||
|
||||
/// @notice Propagates information about stake top-up from the legacy NU
|
||||
/// staking contract to T staking contract. Can be called only by
|
||||
/// the owner or operator.
|
||||
function topUpNu(address operator) external;
|
||||
|
||||
//
|
||||
//
|
||||
// Undelegating a stake (unstaking)
|
||||
//
|
||||
//
|
||||
|
||||
/// @notice Reduces the liquid T stake amount by the provided amount and
|
||||
/// withdraws T to the owner. Reverts if there is at least one
|
||||
/// authorization higher than the sum of the legacy stake and
|
||||
/// remaining liquid T stake or if the unstake amount is higher than
|
||||
/// the liquid T stake amount. Can be called only by the owner or
|
||||
/// operator.
|
||||
function unstakeT(address operator, uint96 amount) external;
|
||||
|
||||
/// @notice Sets the legacy KEEP staking contract active stake amount cached
|
||||
/// in T staking contract to 0. Reverts if the amount of liquid T
|
||||
/// staked in T staking contract is lower than the highest
|
||||
/// application authorization. This function allows to unstake from
|
||||
/// KEEP staking contract and still being able to operate in T
|
||||
/// network and earning rewards based on the liquid T staked. Can be
|
||||
/// called only by the delegation owner and operator.
|
||||
function unstakeKeep(address operator) external;
|
||||
|
||||
/// @notice Reduces cached legacy NU stake amount by the provided amount.
|
||||
/// Reverts if there is at least one authorization higher than the
|
||||
/// sum of remaining legacy NU stake and liquid T stake for that
|
||||
/// operator or if the untaked amount is higher than the cached
|
||||
/// legacy stake amount. If succeeded, the legacy NU stake can be
|
||||
/// partially or fully undelegated on the legacy staking contract.
|
||||
/// This function allows to unstake from NU staking contract and
|
||||
/// still being able to operate in T network and earning rewards
|
||||
/// based on the liquid T staked. Can be called only by the
|
||||
/// delegation owner and operator.
|
||||
function unstakeNu(address operator, uint96 amount) external;
|
||||
|
||||
/// @notice Sets cached legacy stake amount to 0, sets the liquid T stake
|
||||
/// amount to 0 and withdraws all liquid T from the stake to the
|
||||
/// owner. Reverts if there is at least one non-zero authorization.
|
||||
/// Can be called only by the delegation owner and operator.
|
||||
function unstakeAll(address operator) external;
|
||||
|
||||
//
|
||||
//
|
||||
// Keeping information in sync
|
||||
//
|
||||
//
|
||||
|
||||
/// @notice Notifies about the discrepancy between legacy KEEP active stake
|
||||
/// and the amount cached in T staking contract. Slashes the operator
|
||||
/// in case the amount cached is higher than the actual active stake
|
||||
/// amount in KEEP staking contract. Needs to update authorizations
|
||||
/// of all affected applications and execute an involuntary
|
||||
/// allocation decrease on all affected applications. Can be called
|
||||
/// by anyone, notifier receives a reward.
|
||||
function notifyKeepStakeDiscrepancy(address operator) external;
|
||||
|
||||
/// @notice Notifies about the discrepancy between legacy NU active stake
|
||||
/// and the amount cached in T staking contract. Slashes the
|
||||
/// operator in case the amount cached is higher than the actual
|
||||
/// active stake amount in NU staking contract. Needs to update
|
||||
/// authorizations of all affected applications and execute an
|
||||
/// involuntary allocation decrease on all affected applications.
|
||||
/// Can be called by anyone, notifier receives a reward.
|
||||
function notifyNuStakeDiscrepancy(address operator) external;
|
||||
|
||||
/// @notice Sets the penalty amount for stake discrepancy and reward
|
||||
/// multiplier for reporting it. The penalty is seized from the
|
||||
/// operator account, and 5% of the penalty, scaled by the
|
||||
/// multiplier, is given to the notifier. The rest of the tokens are
|
||||
/// burned. Can only be called by the Governance. See `seize` function.
|
||||
function setStakeDiscrepancyPenalty(
|
||||
uint96 penalty,
|
||||
uint256 rewardMultiplier
|
||||
) external;
|
||||
|
||||
/// @notice Sets reward in T tokens for notification of misbehaviour
|
||||
/// of one operator. Can only be called by the governance.
|
||||
function setNotificationReward(uint96 reward) external;
|
||||
|
||||
/// @notice Transfer some amount of T tokens as reward for notifications
|
||||
/// of misbehaviour
|
||||
function pushNotificationReward(uint96 reward) external;
|
||||
|
||||
/// @notice Withdraw some amount of T tokens from notifiers treasury.
|
||||
/// Can only be called by the governance.
|
||||
function withdrawNotificationReward(address recipient, uint96 amount)
|
||||
external;
|
||||
|
||||
/// @notice Adds operators to the slashing queue along with the amount that
|
||||
/// should be slashed from each one of them. Can only be called by
|
||||
/// application authorized for all operators in the array.
|
||||
function slash(uint96 amount, address[] memory operators) external;
|
||||
|
||||
/// @notice Adds operators to the slashing queue along with the amount.
|
||||
/// The notifier will receive reward per each operator from
|
||||
/// notifiers treasury. Can only be called by application
|
||||
/// authorized for all operators in the array.
|
||||
function seize(
|
||||
uint96 amount,
|
||||
uint256 rewardMultipier,
|
||||
address notifier,
|
||||
address[] memory operators
|
||||
) external;
|
||||
|
||||
/// @notice Takes the given number of queued slashing operations and
|
||||
/// processes them. Receives 5% of the slashed amount.
|
||||
/// Executes `involuntaryAllocationDecrease` function on each
|
||||
/// affected application.
|
||||
function processSlashing(uint256 count) external;
|
||||
|
||||
//
|
||||
//
|
||||
// Auxiliary functions
|
||||
//
|
||||
//
|
||||
|
||||
/// @notice Returns the authorized stake amount of the operator for the
|
||||
/// application.
|
||||
function authorizedStake(address operator, address application)
|
||||
external
|
||||
view
|
||||
returns (uint96);
|
||||
|
||||
/// @notice Returns staked amount of T, Keep and Nu for the specified
|
||||
/// operator.
|
||||
/// @dev All values are in T denomination
|
||||
function stakes(address operator)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
uint96 tStake,
|
||||
uint96 keepInTStake,
|
||||
uint96 nuInTStake
|
||||
);
|
||||
|
||||
/// @notice Returns start staking timestamp for T stake.
|
||||
/// @dev This value is set at most once, and only when a stake is created
|
||||
/// with T tokens. If a stake is created from a legacy stake,
|
||||
/// this value will remain as zero
|
||||
function getStartTStakingTimestamp(address operator)
|
||||
external
|
||||
view
|
||||
returns (uint256);
|
||||
|
||||
/// @notice Returns staked amount of NU for the specified operator
|
||||
function stakedNu(address operator) external view returns (uint256);
|
||||
|
||||
/// @notice Gets the stake owner, the beneficiary and the authorizer
|
||||
/// for the specified operator address.
|
||||
/// @return owner Stake owner address.
|
||||
/// @return beneficiary Beneficiary address.
|
||||
/// @return authorizer Authorizer address.
|
||||
function rolesOf(address operator)
|
||||
external
|
||||
view
|
||||
returns (
|
||||
address owner,
|
||||
address payable beneficiary,
|
||||
address authorizer
|
||||
);
|
||||
|
||||
/// @notice Returns length of application array
|
||||
function getApplicationsLength() external view returns (uint256);
|
||||
|
||||
/// @notice Returns length of slashing queue
|
||||
function getSlashingQueueLength() external view returns (uint256);
|
||||
|
||||
/// @notice Returns minimum possible stake for T, KEEP or NU in T denomination
|
||||
/// @dev For example, if the given operator has 10 T, 20 KEEP, and
|
||||
/// 30 NU staked, their max authorization is 40, then `getMinStaked`
|
||||
/// for that operator returns 0 for KEEP stake type, 10 for NU stake
|
||||
/// type, and 0 for T stake type. In other words, minimum staked
|
||||
/// amount for the given stake type is the minimum amount of stake
|
||||
/// of the given type that needs to be preserved in the contract to
|
||||
/// satisfy the maximum application authorization given the amounts
|
||||
/// of other stake types for that operator.
|
||||
function getMinStaked(address operator, StakeType stakeTypes)
|
||||
external
|
||||
view
|
||||
returns (uint96);
|
||||
|
||||
/// @notice Returns available amount to authorize for the specified application
|
||||
function getAvailableToAuthorize(address operator, address application)
|
||||
external
|
||||
view
|
||||
returns (uint96);
|
||||
}
|
|
@ -1,11 +1,10 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.3.2 (utils/math/Math.sol)
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
/**
|
||||
* @title Math
|
||||
* @dev Assorted math operations
|
||||
* @dev Standard math utilities missing in the Solidity language.
|
||||
*/
|
||||
library Math {
|
||||
/**
|
||||
|
@ -23,12 +22,22 @@ library Math {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev Calculates the average of two numbers. Since these are integers,
|
||||
* averages of an even and odd number cannot be represented, and will be
|
||||
* rounded down.
|
||||
* @dev Returns the average of two numbers. The result is rounded towards
|
||||
* zero.
|
||||
*/
|
||||
function average(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// (a + b) / 2 can overflow, so we distribute
|
||||
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
|
||||
// (a + b) / 2 can overflow.
|
||||
return (a & b) + (a ^ b) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the ceiling of the division of two numbers.
|
||||
*
|
||||
* This differs from standard division with `/` in that it rounds up instead
|
||||
* of rounding down.
|
||||
*/
|
||||
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// (a + b - 1) / b can overflow on addition, so we distribute.
|
||||
return a / b + (a % b == 0 ? 0 : 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,68 +1,227 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.3.2 (utils/math/SafeMath.sol)
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
// CAUTION
|
||||
// This version of SafeMath should only be used with Solidity 0.8 or later,
|
||||
// because it relies on the compiler's built in overflow checks.
|
||||
|
||||
/**
|
||||
* @title SafeMath
|
||||
* @dev Unsigned math operations with safety checks that revert on error
|
||||
* @dev Wrappers over Solidity's arithmetic operations.
|
||||
*
|
||||
* NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
|
||||
* now has built in overflow checking.
|
||||
*/
|
||||
library SafeMath {
|
||||
/**
|
||||
* @dev Multiplies two unsigned integers, reverts on overflow.
|
||||
* @dev Returns the addition of two unsigned integers, with an overflow flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
|
||||
// benefit is lost if 'b' is also tested.
|
||||
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
|
||||
if (a == 0) {
|
||||
return 0;
|
||||
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
unchecked {
|
||||
uint256 c = a + b;
|
||||
if (c < a) return (false, 0);
|
||||
return (true, c);
|
||||
}
|
||||
|
||||
uint256 c = a * b;
|
||||
require(c / a == b);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Integer division of two unsigned integers truncating the quotient, reverts on division by zero.
|
||||
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
// Solidity only automatically asserts when dividing by 0
|
||||
require(b > 0);
|
||||
uint256 c = a / b;
|
||||
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
|
||||
|
||||
return c;
|
||||
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
unchecked {
|
||||
if (b > a) return (false, 0);
|
||||
return (true, a - b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Subtracts two unsigned integers, reverts on overflow (i.e. if subtrahend is greater than minuend).
|
||||
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b <= a);
|
||||
uint256 c = a - b;
|
||||
|
||||
return c;
|
||||
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
unchecked {
|
||||
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
|
||||
// benefit is lost if 'b' is also tested.
|
||||
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
|
||||
if (a == 0) return (true, 0);
|
||||
uint256 c = a * b;
|
||||
if (c / a != b) return (false, 0);
|
||||
return (true, c);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Adds two unsigned integers, reverts on overflow.
|
||||
* @dev Returns the division of two unsigned integers, with a division by zero flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
unchecked {
|
||||
if (b == 0) return (false, 0);
|
||||
return (true, a / b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
|
||||
unchecked {
|
||||
if (b == 0) return (false, 0);
|
||||
return (true, a % b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the addition of two unsigned integers, reverting on
|
||||
* overflow.
|
||||
*
|
||||
* Counterpart to Solidity's `+` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Addition cannot overflow.
|
||||
*/
|
||||
function add(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
uint256 c = a + b;
|
||||
require(c >= a);
|
||||
|
||||
return c;
|
||||
return a + b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Divides two unsigned integers and returns the remainder (unsigned integer modulo),
|
||||
* reverts when dividing by zero.
|
||||
* @dev Returns the subtraction of two unsigned integers, reverting on
|
||||
* overflow (when the result is negative).
|
||||
*
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the multiplication of two unsigned integers, reverting on
|
||||
* overflow.
|
||||
*
|
||||
* Counterpart to Solidity's `*` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Multiplication cannot overflow.
|
||||
*/
|
||||
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the integer division of two unsigned integers, reverting on
|
||||
* division by zero. The result is rounded towards zero.
|
||||
*
|
||||
* Counterpart to Solidity's `/` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function div(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
return a / b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
|
||||
* reverting when dividing by zero.
|
||||
*
|
||||
* Counterpart to Solidity's `%` operator. This function uses a `revert`
|
||||
* opcode (which leaves remaining gas untouched) while Solidity uses an
|
||||
* invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
|
||||
require(b != 0);
|
||||
return a % b;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
|
||||
* overflow (when the result is negative).
|
||||
*
|
||||
* CAUTION: This function is deprecated because it requires allocating memory for the error
|
||||
* message unnecessarily. For custom revert reasons use {trySub}.
|
||||
*
|
||||
* Counterpart to Solidity's `-` operator.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - Subtraction cannot overflow.
|
||||
*/
|
||||
function sub(
|
||||
uint256 a,
|
||||
uint256 b,
|
||||
string memory errorMessage
|
||||
) internal pure returns (uint256) {
|
||||
unchecked {
|
||||
require(b <= a, errorMessage);
|
||||
return a - b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
|
||||
* division by zero. The result is rounded towards zero.
|
||||
*
|
||||
* Counterpart to Solidity's `/` operator. Note: this function uses a
|
||||
* `revert` opcode (which leaves remaining gas untouched) while Solidity
|
||||
* uses an invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function div(
|
||||
uint256 a,
|
||||
uint256 b,
|
||||
string memory errorMessage
|
||||
) internal pure returns (uint256) {
|
||||
unchecked {
|
||||
require(b > 0, errorMessage);
|
||||
return a / b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
|
||||
* reverting with custom message when dividing by zero.
|
||||
*
|
||||
* CAUTION: This function is deprecated because it requires allocating memory for the error
|
||||
* message unnecessarily. For custom revert reasons use {tryMod}.
|
||||
*
|
||||
* Counterpart to Solidity's `%` operator. This function uses a `revert`
|
||||
* opcode (which leaves remaining gas untouched) while Solidity uses an
|
||||
* invalid opcode to revert (consuming all remaining gas).
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - The divisor cannot be zero.
|
||||
*/
|
||||
function mod(
|
||||
uint256 a,
|
||||
uint256 b,
|
||||
string memory errorMessage
|
||||
) internal pure returns (uint256) {
|
||||
unchecked {
|
||||
require(b > 0, errorMessage);
|
||||
return a % b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,63 +1,62 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
pragma solidity ^0.7.0;
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.3.2 (proxy/utils/Initializable.sol)
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
/**
|
||||
* @title Initializable
|
||||
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
|
||||
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
|
||||
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
|
||||
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
|
||||
*
|
||||
* @dev Helper contract to support initializer functions. To use it, replace
|
||||
* the constructor with a function that has the `initializer` modifier.
|
||||
* WARNING: Unlike constructors, initializer functions must be manually
|
||||
* invoked. This applies both to deploying an Initializable contract, as well
|
||||
* as extending an Initializable contract via inheritance.
|
||||
* WARNING: When used with inheritance, manual care must be taken to not invoke
|
||||
* a parent initializer twice, or ensure that all initializers are idempotent,
|
||||
* because this is not dealt with automatically as with constructors.
|
||||
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
|
||||
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
|
||||
*
|
||||
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
|
||||
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
|
||||
*
|
||||
* [CAUTION]
|
||||
* ====
|
||||
* Avoid leaving a contract uninitialized.
|
||||
*
|
||||
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
|
||||
* contract, which may impact the proxy. To initialize the implementation contract, you can either invoke the
|
||||
* initializer manually, or you can include a constructor to automatically mark it as initialized when it is deployed:
|
||||
*
|
||||
* [.hljs-theme-light.nopadding]
|
||||
* ```
|
||||
* /// @custom:oz-upgrades-unsafe-allow constructor
|
||||
* constructor() initializer {}
|
||||
* ```
|
||||
* ====
|
||||
*/
|
||||
contract Initializable {
|
||||
abstract contract Initializable {
|
||||
/**
|
||||
* @dev Indicates that the contract has been initialized.
|
||||
*/
|
||||
bool private _initialized;
|
||||
|
||||
/**
|
||||
* @dev Indicates that the contract has been initialized.
|
||||
*/
|
||||
bool private initialized;
|
||||
/**
|
||||
* @dev Indicates that the contract is in the process of being initialized.
|
||||
*/
|
||||
bool private _initializing;
|
||||
|
||||
/**
|
||||
* @dev Indicates that the contract is in the process of being initialized.
|
||||
*/
|
||||
bool private initializing;
|
||||
/**
|
||||
* @dev Modifier to protect an initializer function from being invoked twice.
|
||||
*/
|
||||
modifier initializer() {
|
||||
require(_initializing || !_initialized, "Initializable: contract is already initialized");
|
||||
|
||||
/**
|
||||
* @dev Modifier to use in the initializer function of a contract.
|
||||
*/
|
||||
modifier initializer() {
|
||||
require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized");
|
||||
bool isTopLevelCall = !_initializing;
|
||||
if (isTopLevelCall) {
|
||||
_initializing = true;
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
bool isTopLevelCall = !initializing;
|
||||
if (isTopLevelCall) {
|
||||
initializing = true;
|
||||
initialized = true;
|
||||
_;
|
||||
|
||||
if (isTopLevelCall) {
|
||||
_initializing = false;
|
||||
}
|
||||
}
|
||||
|
||||
_;
|
||||
|
||||
if (isTopLevelCall) {
|
||||
initializing = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Returns true if and only if the function is running in the constructor
|
||||
function isConstructor() private view returns (bool) {
|
||||
// extcodesize checks the size of the code stored in an address, and
|
||||
// address returns the current address. Since the code is still not
|
||||
// deployed when running a constructor, any checks on its code size will
|
||||
// yield zero, making it an effective way to detect if a contract is
|
||||
// under construction or not.
|
||||
address self = address(this);
|
||||
uint256 cs;
|
||||
assembly { cs := extcodesize(self) }
|
||||
return cs == 0;
|
||||
}
|
||||
|
||||
// Reserved storage space to allow for layout changes in the future.
|
||||
uint256[50] private ______gap;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "zeppelin/token/ERC20/IERC20.sol";
|
||||
import "zeppelin/math/SafeMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
|
@ -20,7 +19,6 @@ import "zeppelin/math/SafeMath.sol";
|
|||
* compliant implementations may not do it.
|
||||
*/
|
||||
contract ERC20 is IERC20 {
|
||||
using SafeMath for uint256;
|
||||
|
||||
mapping (address => uint256) private _balances;
|
||||
|
||||
|
@ -95,7 +93,7 @@ contract ERC20 is IERC20 {
|
|||
*/
|
||||
function transferFrom(address from, address to, uint256 value) public override returns (bool) {
|
||||
_transfer(from, to, value);
|
||||
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
|
||||
_approve(from, msg.sender, _allowed[from][msg.sender] - value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -110,7 +108,7 @@ contract ERC20 is IERC20 {
|
|||
* @param addedValue The amount of tokens to increase the allowance by.
|
||||
*/
|
||||
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
|
||||
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
|
||||
_approve(msg.sender, spender, _allowed[msg.sender][spender] + addedValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -125,7 +123,7 @@ contract ERC20 is IERC20 {
|
|||
* @param subtractedValue The amount of tokens to decrease the allowance by.
|
||||
*/
|
||||
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
|
||||
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
|
||||
_approve(msg.sender, spender, _allowed[msg.sender][spender] - subtractedValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -138,8 +136,8 @@ contract ERC20 is IERC20 {
|
|||
function _transfer(address from, address to, uint256 value) internal {
|
||||
require(to != address(0));
|
||||
|
||||
_balances[from] = _balances[from].sub(value);
|
||||
_balances[to] = _balances[to].add(value);
|
||||
_balances[from] -= value;
|
||||
_balances[to] += value;
|
||||
emit Transfer(from, to, value);
|
||||
}
|
||||
|
||||
|
@ -153,8 +151,8 @@ contract ERC20 is IERC20 {
|
|||
function _mint(address account, uint256 value) internal {
|
||||
require(account != address(0));
|
||||
|
||||
_totalSupply = _totalSupply.add(value);
|
||||
_balances[account] = _balances[account].add(value);
|
||||
_totalSupply += value;
|
||||
_balances[account] += value;
|
||||
emit Transfer(address(0), account, value);
|
||||
}
|
||||
|
||||
|
@ -167,8 +165,8 @@ contract ERC20 is IERC20 {
|
|||
function _burn(address account, uint256 value) internal {
|
||||
require(account != address(0));
|
||||
|
||||
_totalSupply = _totalSupply.sub(value);
|
||||
_balances[account] = _balances[account].sub(value);
|
||||
_totalSupply -= value;
|
||||
_balances[account] -= value;
|
||||
emit Transfer(account, address(0), value);
|
||||
}
|
||||
|
||||
|
@ -196,7 +194,7 @@ contract ERC20 is IERC20 {
|
|||
*/
|
||||
function _burnFrom(address account, uint256 value) internal {
|
||||
_burn(account, value);
|
||||
_approve(account, msg.sender, _allowed[account][msg.sender].sub(value));
|
||||
_approve(account, msg.sender, _allowed[account][msg.sender] - value);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "./IERC20.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,44 +1,99 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.3.2 (token/ERC20/utils/SafeERC20.sol)
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "zeppelin/token/ERC20/IERC20.sol";
|
||||
import "zeppelin/math/SafeMath.sol";
|
||||
|
||||
import "zeppelin/utils/Address.sol";
|
||||
|
||||
/**
|
||||
* @title SafeERC20
|
||||
* @dev Wrappers around ERC20 operations that throw on failure.
|
||||
* To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
|
||||
* @dev Wrappers around ERC20 operations that throw on failure (when the token
|
||||
* contract returns false). Tokens that return no value (and instead revert or
|
||||
* throw on failure) are also supported, non-reverting calls are assumed to be
|
||||
* successful.
|
||||
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
|
||||
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
|
||||
*/
|
||||
library SafeERC20 {
|
||||
using SafeMath for uint256;
|
||||
using Address for address;
|
||||
|
||||
function safeTransfer(IERC20 token, address to, uint256 value) internal {
|
||||
require(token.transfer(to, value));
|
||||
function safeTransfer(
|
||||
IERC20 token,
|
||||
address to,
|
||||
uint256 value
|
||||
) internal {
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
|
||||
}
|
||||
|
||||
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
|
||||
require(token.transferFrom(from, to, value));
|
||||
function safeTransferFrom(
|
||||
IERC20 token,
|
||||
address from,
|
||||
address to,
|
||||
uint256 value
|
||||
) internal {
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
|
||||
}
|
||||
|
||||
function safeApprove(IERC20 token, address spender, uint256 value) internal {
|
||||
/**
|
||||
* @dev Deprecated. This function has issues similar to the ones found in
|
||||
* {IERC20-approve}, and its usage is discouraged.
|
||||
*
|
||||
* Whenever possible, use {safeIncreaseAllowance} and
|
||||
* {safeDecreaseAllowance} instead.
|
||||
*/
|
||||
function safeApprove(
|
||||
IERC20 token,
|
||||
address spender,
|
||||
uint256 value
|
||||
) internal {
|
||||
// safeApprove should only be called when setting an initial allowance,
|
||||
// or when resetting it to zero. To increase and decrease it, use
|
||||
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
|
||||
require((value == 0) || (token.allowance(msg.sender, spender) == 0));
|
||||
require(token.approve(spender, value));
|
||||
require(
|
||||
(value == 0) || (token.allowance(address(this), spender) == 0),
|
||||
"SafeERC20: approve from non-zero to non-zero allowance"
|
||||
);
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
|
||||
}
|
||||
|
||||
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
|
||||
uint256 newAllowance = token.allowance(address(this), spender).add(value);
|
||||
require(token.approve(spender, newAllowance));
|
||||
function safeIncreaseAllowance(
|
||||
IERC20 token,
|
||||
address spender,
|
||||
uint256 value
|
||||
) internal {
|
||||
uint256 newAllowance = token.allowance(address(this), spender) + value;
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
|
||||
}
|
||||
|
||||
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
|
||||
uint256 newAllowance = token.allowance(address(this), spender).sub(value);
|
||||
require(token.approve(spender, newAllowance));
|
||||
function safeDecreaseAllowance(
|
||||
IERC20 token,
|
||||
address spender,
|
||||
uint256 value
|
||||
) internal {
|
||||
unchecked {
|
||||
uint256 oldAllowance = token.allowance(address(this), spender);
|
||||
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
|
||||
uint256 newAllowance = oldAllowance - value;
|
||||
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
|
||||
* on the return value: the return value is optional (but if data is returned, it must not be false).
|
||||
* @param token The token targeted by the call.
|
||||
* @param data The call data (encoded using abi.encode or one of its variants).
|
||||
*/
|
||||
function _callOptionalReturn(IERC20 token, bytes memory data) private {
|
||||
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
|
||||
// we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
|
||||
// the target address contains contract code and also asserts for success in the low-level call.
|
||||
|
||||
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
|
||||
if (returndata.length > 0) {
|
||||
// Return data is optional
|
||||
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts v4.3.2 (utils/Address.sol)
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
/**
|
||||
* @dev Collection of functions related to the address type
|
||||
|
@ -24,14 +25,15 @@ library Address {
|
|||
* ====
|
||||
*/
|
||||
function isContract(address account) internal view returns (bool) {
|
||||
// According to EIP-1052, 0x0 is the value returned for not-yet created accounts
|
||||
// and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
|
||||
// for accounts without code, i.e. `keccak256('')`
|
||||
bytes32 codehash;
|
||||
bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
|
||||
// solhint-disable-next-line no-inline-assembly
|
||||
assembly { codehash := extcodehash(account) }
|
||||
return (codehash != accountHash && codehash != 0x0);
|
||||
// This method relies on extcodesize, which returns 0 for contracts in
|
||||
// construction, since the code is only stored at the end of the
|
||||
// constructor execution.
|
||||
|
||||
uint256 size;
|
||||
assembly {
|
||||
size := extcodesize(account)
|
||||
}
|
||||
return size > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -49,14 +51,167 @@ library Address {
|
|||
* taken to not create reentrancy vulnerabilities. Consider using
|
||||
* {ReentrancyGuard} or the
|
||||
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
|
||||
*
|
||||
* _Available since v2.4.0._
|
||||
*/
|
||||
function sendValue(address payable recipient, uint256 amount) internal {
|
||||
require(address(this).balance >= amount, "Address: insufficient balance");
|
||||
|
||||
// solhint-disable-next-line avoid-call-value
|
||||
(bool success, ) = recipient.call{value: amount}("");
|
||||
require(success, "Address: unable to send value, recipient may have reverted");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Performs a Solidity function call using a low level `call`. A
|
||||
* plain `call` is an unsafe replacement for a function call: use this
|
||||
* function instead.
|
||||
*
|
||||
* If `target` reverts with a revert reason, it is bubbled up by this
|
||||
* function (like regular Solidity function calls).
|
||||
*
|
||||
* Returns the raw returned data. To convert to the expected return value,
|
||||
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - `target` must be a contract.
|
||||
* - calling `target` with `data` must not revert.
|
||||
*
|
||||
* _Available since v3.1._
|
||||
*/
|
||||
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
|
||||
return functionCall(target, data, "Address: low-level call failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
|
||||
* `errorMessage` as a fallback revert reason when `target` reverts.
|
||||
*
|
||||
* _Available since v3.1._
|
||||
*/
|
||||
function functionCall(
|
||||
address target,
|
||||
bytes memory data,
|
||||
string memory errorMessage
|
||||
) internal returns (bytes memory) {
|
||||
return functionCallWithValue(target, data, 0, errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
|
||||
* but also transferring `value` wei to `target`.
|
||||
*
|
||||
* Requirements:
|
||||
*
|
||||
* - the calling contract must have an ETH balance of at least `value`.
|
||||
* - the called Solidity function must be `payable`.
|
||||
*
|
||||
* _Available since v3.1._
|
||||
*/
|
||||
function functionCallWithValue(
|
||||
address target,
|
||||
bytes memory data,
|
||||
uint256 value
|
||||
) internal returns (bytes memory) {
|
||||
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
|
||||
* with `errorMessage` as a fallback revert reason when `target` reverts.
|
||||
*
|
||||
* _Available since v3.1._
|
||||
*/
|
||||
function functionCallWithValue(
|
||||
address target,
|
||||
bytes memory data,
|
||||
uint256 value,
|
||||
string memory errorMessage
|
||||
) internal returns (bytes memory) {
|
||||
require(address(this).balance >= value, "Address: insufficient balance for call");
|
||||
require(isContract(target), "Address: call to non-contract");
|
||||
|
||||
(bool success, bytes memory returndata) = target.call{value: value}(data);
|
||||
return verifyCallResult(success, returndata, errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
|
||||
* but performing a static call.
|
||||
*
|
||||
* _Available since v3.3._
|
||||
*/
|
||||
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
|
||||
return functionStaticCall(target, data, "Address: low-level static call failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
|
||||
* but performing a static call.
|
||||
*
|
||||
* _Available since v3.3._
|
||||
*/
|
||||
function functionStaticCall(
|
||||
address target,
|
||||
bytes memory data,
|
||||
string memory errorMessage
|
||||
) internal view returns (bytes memory) {
|
||||
require(isContract(target), "Address: static call to non-contract");
|
||||
|
||||
(bool success, bytes memory returndata) = target.staticcall(data);
|
||||
return verifyCallResult(success, returndata, errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
|
||||
* but performing a delegate call.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
|
||||
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
|
||||
* but performing a delegate call.
|
||||
*
|
||||
* _Available since v3.4._
|
||||
*/
|
||||
function functionDelegateCall(
|
||||
address target,
|
||||
bytes memory data,
|
||||
string memory errorMessage
|
||||
) internal returns (bytes memory) {
|
||||
require(isContract(target), "Address: delegate call to non-contract");
|
||||
|
||||
(bool success, bytes memory returndata) = target.delegatecall(data);
|
||||
return verifyCallResult(success, returndata, errorMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
|
||||
* revert reason using the provided one.
|
||||
*
|
||||
* _Available since v4.3._
|
||||
*/
|
||||
function verifyCallResult(
|
||||
bool success,
|
||||
bytes memory returndata,
|
||||
string memory errorMessage
|
||||
) internal pure returns (bytes memory) {
|
||||
if (success) {
|
||||
return returndata;
|
||||
} else {
|
||||
// Look for revert reason and bubble it up if present
|
||||
if (returndata.length > 0) {
|
||||
// The easiest way to bubble the revert reason is using memory via assembly
|
||||
|
||||
assembly {
|
||||
let returndata_size := mload(returndata)
|
||||
revert(add(32, returndata), returndata_size)
|
||||
}
|
||||
} else {
|
||||
revert(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/Adjudicator.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/lib/SignatureVerifier.sol";
|
||||
|
@ -50,7 +50,7 @@ contract SignatureVerifierMock {
|
|||
bytes memory _message,
|
||||
bytes memory _signature,
|
||||
bytes memory _publicKey,
|
||||
byte _version
|
||||
bytes1 _version
|
||||
)
|
||||
public
|
||||
view
|
||||
|
@ -61,7 +61,7 @@ contract SignatureVerifierMock {
|
|||
|
||||
function hashEIP191(
|
||||
bytes memory _message,
|
||||
byte _version
|
||||
bytes1 _version
|
||||
)
|
||||
public
|
||||
view
|
||||
|
@ -81,30 +81,30 @@ contract UmbralDeserializerMock {
|
|||
|
||||
function toCapsule(bytes memory _capsuleBytes)
|
||||
public pure returns (
|
||||
byte pointESign,
|
||||
bytes1 pointESign,
|
||||
bytes32 pointEXCoord,
|
||||
byte pointVSign,
|
||||
bytes1 pointVSign,
|
||||
bytes32 pointVXCoord,
|
||||
bytes32 bnSig
|
||||
)
|
||||
{
|
||||
UmbralDeserializer.Capsule memory capsule = _capsuleBytes.toCapsule();
|
||||
pointESign = byte(capsule.pointE.sign);
|
||||
pointESign = bytes1(capsule.pointE.sign);
|
||||
pointEXCoord = bytes32(capsule.pointE.xCoord);
|
||||
pointVSign = byte(capsule.pointV.sign);
|
||||
pointVSign = bytes1(capsule.pointV.sign);
|
||||
pointVXCoord = bytes32(capsule.pointV.xCoord);
|
||||
bnSig = bytes32(capsule.bnSig);
|
||||
}
|
||||
|
||||
function toCorrectnessProof(bytes memory _proofBytes)
|
||||
public pure returns (
|
||||
byte pointE2Sign,
|
||||
bytes1 pointE2Sign,
|
||||
bytes32 pointE2XCoord,
|
||||
byte pointV2Sign,
|
||||
bytes1 pointV2Sign,
|
||||
bytes32 pointV2XCoord,
|
||||
byte pointKFragCommitmentSign,
|
||||
bytes1 pointKFragCommitmentSign,
|
||||
bytes32 pointKFragCommitmentXCoord,
|
||||
byte pointKFragPokSign,
|
||||
bytes1 pointKFragPokSign,
|
||||
bytes32 pointKFragPokXCoord,
|
||||
bytes32 bnSig,
|
||||
bytes memory kFragSignature,
|
||||
|
@ -112,13 +112,13 @@ contract UmbralDeserializerMock {
|
|||
)
|
||||
{
|
||||
UmbralDeserializer.CorrectnessProof memory proof = _proofBytes.toCorrectnessProof();
|
||||
pointE2Sign = byte(proof.pointE2.sign);
|
||||
pointE2Sign = bytes1(proof.pointE2.sign);
|
||||
pointE2XCoord = bytes32(proof.pointE2.xCoord);
|
||||
pointV2Sign = byte(proof.pointV2.sign);
|
||||
pointV2Sign = bytes1(proof.pointV2.sign);
|
||||
pointV2XCoord = bytes32(proof.pointV2.xCoord);
|
||||
pointKFragCommitmentSign = byte(proof.pointKFragCommitment.sign);
|
||||
pointKFragCommitmentSign = bytes1(proof.pointKFragCommitment.sign);
|
||||
pointKFragCommitmentXCoord = bytes32(proof.pointKFragCommitment.xCoord);
|
||||
pointKFragPokSign = byte(proof.pointKFragPok.sign);
|
||||
pointKFragPokSign = bytes1(proof.pointKFragPok.sign);
|
||||
pointKFragPokXCoord = bytes32(proof.pointKFragPok.xCoord);
|
||||
bnSig = bytes32(proof.bnSig);
|
||||
kFragSignature = proof.kFragSignature;
|
||||
|
@ -128,13 +128,13 @@ contract UmbralDeserializerMock {
|
|||
// `toCapsuleFrag` is split into two methods because of EVM stack problems with many variables
|
||||
function toCorrectnessProofFromCapsuleFrag(bytes memory _cFragBytes)
|
||||
public pure returns (
|
||||
byte pointE2Sign,
|
||||
bytes1 pointE2Sign,
|
||||
bytes32 pointE2XCoord,
|
||||
byte pointV2Sign,
|
||||
bytes1 pointV2Sign,
|
||||
bytes32 pointV2XCoord,
|
||||
byte pointKFragCommitmentSign,
|
||||
bytes1 pointKFragCommitmentSign,
|
||||
bytes32 pointKFragCommitmentXCoord,
|
||||
byte pointKFragPokSign,
|
||||
bytes1 pointKFragPokSign,
|
||||
bytes32 pointKFragPokXCoord,
|
||||
bytes32 bnSig,
|
||||
bytes memory kFragSignature,
|
||||
|
@ -143,13 +143,13 @@ contract UmbralDeserializerMock {
|
|||
{
|
||||
UmbralDeserializer.CapsuleFrag memory cFrag = _cFragBytes.toCapsuleFrag();
|
||||
UmbralDeserializer.CorrectnessProof memory proof = cFrag.proof;
|
||||
pointE2Sign = byte(proof.pointE2.sign);
|
||||
pointE2Sign = bytes1(proof.pointE2.sign);
|
||||
pointE2XCoord = bytes32(proof.pointE2.xCoord);
|
||||
pointV2Sign = byte(proof.pointV2.sign);
|
||||
pointV2Sign = bytes1(proof.pointV2.sign);
|
||||
pointV2XCoord = bytes32(proof.pointV2.xCoord);
|
||||
pointKFragCommitmentSign = byte(proof.pointKFragCommitment.sign);
|
||||
pointKFragCommitmentSign = bytes1(proof.pointKFragCommitment.sign);
|
||||
pointKFragCommitmentXCoord = bytes32(proof.pointKFragCommitment.xCoord);
|
||||
pointKFragPokSign = byte(proof.pointKFragPok.sign);
|
||||
pointKFragPokSign = bytes1(proof.pointKFragPok.sign);
|
||||
pointKFragPokXCoord = bytes32(proof.pointKFragPok.xCoord);
|
||||
bnSig = bytes32(proof.bnSig);
|
||||
kFragSignature = proof.kFragSignature;
|
||||
|
@ -158,22 +158,22 @@ contract UmbralDeserializerMock {
|
|||
|
||||
function toCapsuleFrag(bytes memory _cFragBytes)
|
||||
public pure returns (
|
||||
byte pointE1Sign,
|
||||
bytes1 pointE1Sign,
|
||||
bytes32 pointE1XCoord,
|
||||
byte pointV1Sign,
|
||||
bytes1 pointV1Sign,
|
||||
bytes32 pointV1XCoord,
|
||||
bytes32 kFragId,
|
||||
byte pointPrecursorSign,
|
||||
bytes1 pointPrecursorSign,
|
||||
bytes32 pointPrecursorXCoord
|
||||
)
|
||||
{
|
||||
UmbralDeserializer.CapsuleFrag memory cFrag = _cFragBytes.toCapsuleFrag();
|
||||
pointE1Sign = byte(cFrag.pointE1.sign);
|
||||
pointE1Sign = bytes1(cFrag.pointE1.sign);
|
||||
pointE1XCoord = bytes32(cFrag.pointE1.xCoord);
|
||||
pointV1Sign = byte(cFrag.pointV1.sign);
|
||||
pointV1Sign = bytes1(cFrag.pointV1.sign);
|
||||
pointV1XCoord = bytes32(cFrag.pointV1.xCoord);
|
||||
kFragId = cFrag.kFragId;
|
||||
pointPrecursorSign = byte(cFrag.pointPrecursor.sign);
|
||||
pointPrecursorSign = bytes1(cFrag.pointPrecursor.sign);
|
||||
pointPrecursorXCoord = bytes32(cFrag.pointPrecursor.xCoord);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/PolicyManager.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/NuCypherToken.sol";
|
||||
|
@ -61,7 +61,7 @@ contract PolicyManagerForStakingContractMock {
|
|||
function withdraw() public returns (uint256) {
|
||||
uint256 value = address(this).balance;
|
||||
require(value > 0);
|
||||
msg.sender.transfer(value);
|
||||
payable(msg.sender).transfer(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ contract WorkLockForStakingContractMock {
|
|||
function cancelBid() external {
|
||||
uint256 value = depositedETH;
|
||||
depositedETH = 0;
|
||||
msg.sender.transfer(value);
|
||||
payable(msg.sender).transfer(value);
|
||||
}
|
||||
|
||||
function sendCompensation() external payable {
|
||||
|
@ -110,7 +110,7 @@ contract WorkLockForStakingContractMock {
|
|||
function withdrawCompensation() external {
|
||||
uint256 value = compensationValue;
|
||||
compensationValue = 0;
|
||||
msg.sender.transfer(value);
|
||||
payable(msg.sender).transfer(value);
|
||||
}
|
||||
|
||||
function setClaimedTokens(uint256 _claimedTokens) external {
|
||||
|
@ -133,7 +133,7 @@ contract WorkLockForStakingContractMock {
|
|||
function refund() external returns (uint256) {
|
||||
uint256 value = refundETH;
|
||||
refundETH = 0;
|
||||
msg.sender.transfer(value);
|
||||
payable(msg.sender).transfer(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ contract DestroyableStakingInterface {
|
|||
}
|
||||
|
||||
function destroy() public {
|
||||
selfdestruct(msg.sender);
|
||||
selfdestruct(payable(msg.sender));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ contract SimpleStakingContract is AbstractStakingContract, Ownable {
|
|||
function withdrawETH() public override onlyOwner {
|
||||
uint256 balance = address(this).balance;
|
||||
require(balance != 0);
|
||||
msg.sender.sendValue(balance);
|
||||
payable(msg.sender).sendValue(balance);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/StakingEscrow.sol";
|
||||
|
@ -13,26 +13,17 @@ contract EnhancedStakingEscrow is StakingEscrow {
|
|||
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
WorkLockInterface _workLock
|
||||
WorkLockInterface _workLock,
|
||||
IStaking _tStaking
|
||||
)
|
||||
StakingEscrow(
|
||||
_token,
|
||||
_workLock
|
||||
_workLock,
|
||||
_tStaking
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
function testSlashStaker(
|
||||
address _staker,
|
||||
uint256 _penalty,
|
||||
address _investigator,
|
||||
uint256 _reward
|
||||
)
|
||||
external
|
||||
{
|
||||
slashStaker(_staker, _penalty, _investigator, _reward);
|
||||
}
|
||||
|
||||
function setStaker(address _staker, uint256 _value, uint16 _lastCommittedPeriod) external {
|
||||
StakerInfo storage info = stakerInfo[_staker];
|
||||
info.value = _value;
|
||||
|
@ -50,11 +41,13 @@ contract StakingEscrowBad is StakingEscrow {
|
|||
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
WorkLockInterface _workLock
|
||||
WorkLockInterface _workLock,
|
||||
IStaking _tStaking
|
||||
)
|
||||
StakingEscrow(
|
||||
_token,
|
||||
_workLock
|
||||
_workLock,
|
||||
_tStaking
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -73,11 +66,13 @@ contract StakingEscrowV2Mock is StakingEscrow {
|
|||
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
WorkLockInterface _workLock
|
||||
WorkLockInterface _workLock,
|
||||
IStaking _tStaking
|
||||
)
|
||||
StakingEscrow(
|
||||
_token,
|
||||
_workLock
|
||||
_workLock,
|
||||
_tStaking
|
||||
)
|
||||
{
|
||||
valueToCheck = 2;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
contract OldPolicyManagerMock {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/NuCypherToken.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "./ContractV1.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/proxy/Upgradeable.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/proxy/Upgradeable.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "./ContractV2.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/proxy/Upgradeable.sol";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/proxy/Upgradeable.sol";
|
||||
|
@ -34,7 +34,7 @@ contract Destroyable is Upgradeable {
|
|||
}
|
||||
|
||||
function destroy() public {
|
||||
selfdestruct(msg.sender);
|
||||
selfdestruct(payable(msg.sender));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
import "contracts/proxy/Upgradeable.sol";
|
||||
|
|
Loading…
Reference in New Issue