编译器
0.8.19+commit.7dd6d404
文件 1 的 18:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
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");
}
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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 2 的 18:AttoDecimal.sol
pragma solidity ^0.8.6;
library AttoDecimal {
struct Instance {
uint256 mantissa;
}
uint256 internal constant BASE = 10;
uint256 internal constant EXPONENTIATION = 18;
uint256 internal constant ONE_MANTISSA = BASE**EXPONENTIATION;
uint256 internal constant ONE_TENTH_MANTISSA = ONE_MANTISSA / 10;
uint256 internal constant HALF_MANTISSA = ONE_MANTISSA / 2;
uint256 internal constant SQUARED_ONE_MANTISSA = ONE_MANTISSA * ONE_MANTISSA;
uint256 internal constant MAX_INTEGER = type(uint256).max / ONE_MANTISSA;
function maximum() internal pure returns (Instance memory) {
return Instance({mantissa: type(uint256).max});
}
function zero() internal pure returns (Instance memory) {
return Instance({mantissa: 0});
}
function one() internal pure returns (Instance memory) {
return Instance({mantissa: ONE_MANTISSA});
}
function convert(uint256 integer) internal pure returns (Instance memory) {
return Instance({mantissa: integer * ONE_MANTISSA});
}
function compare(Instance memory a, Instance memory b) internal pure returns (int8) {
if (a.mantissa < b.mantissa) return -1;
return int8(a.mantissa > b.mantissa ? 1 : 0);
}
function compare(Instance memory a, uint256 b) internal pure returns (int8) {
return compare(a, convert(b));
}
function add(Instance memory a, Instance memory b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa + b.mantissa});
}
function add(Instance memory a, uint256 b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa + b * ONE_MANTISSA});
}
function sub(Instance memory a, Instance memory b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa - b.mantissa});
}
function sub(Instance memory a, uint256 b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa - b * ONE_MANTISSA});
}
function sub(uint256 a, Instance memory b) internal pure returns (Instance memory) {
return Instance({mantissa: a * ONE_MANTISSA - b.mantissa});
}
function mul(Instance memory a, Instance memory b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa * b.mantissa / ONE_MANTISSA});
}
function mul(Instance memory a, uint256 b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa * b});
}
function div(Instance memory a, Instance memory b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa * ONE_MANTISSA / b.mantissa});
}
function div(Instance memory a, uint256 b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa / b});
}
function div(uint256 a, Instance memory b) internal pure returns (Instance memory) {
return Instance({mantissa: a * SQUARED_ONE_MANTISSA / b.mantissa});
}
function div(uint256 a, uint256 b) internal pure returns (Instance memory) {
return Instance({mantissa: a * ONE_MANTISSA / b});
}
function idiv(Instance memory a, Instance memory b) internal pure returns (uint256) {
return a.mantissa / b.mantissa;
}
function idiv(Instance memory a, uint256 b) internal pure returns (uint256) {
return a.mantissa / (b * ONE_MANTISSA);
}
function idiv(uint256 a, Instance memory b) internal pure returns (uint256) {
return a * ONE_MANTISSA / b.mantissa;
}
function mod(Instance memory a, Instance memory b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa % b.mantissa});
}
function mod(Instance memory a, uint256 b) internal pure returns (Instance memory) {
return Instance({mantissa: a.mantissa % (b * ONE_MANTISSA)});
}
function mod(uint256 a, Instance memory b) internal pure returns (Instance memory) {
if (a > MAX_INTEGER) return Instance({mantissa: a % b.mantissa * ONE_MANTISSA % b.mantissa});
return Instance({mantissa: a * ONE_MANTISSA % b.mantissa});
}
function floor(Instance memory a) internal pure returns (uint256) {
return a.mantissa / ONE_MANTISSA;
}
function ceil(Instance memory a) internal pure returns (uint256) {
return (a.mantissa / ONE_MANTISSA) + (a.mantissa % ONE_MANTISSA > 0 ? 1 : 0);
}
function round(Instance memory a) internal pure returns (uint256) {
return (a.mantissa / ONE_MANTISSA) + ((a.mantissa / ONE_TENTH_MANTISSA) % 10 >= 5 ? 1 : 0);
}
function eq(Instance memory a, Instance memory b) internal pure returns (bool) {
return a.mantissa == b.mantissa;
}
function eq(Instance memory a, uint256 b) internal pure returns (bool) {
if (b > MAX_INTEGER) return false;
return a.mantissa == b * ONE_MANTISSA;
}
function gt(Instance memory a, Instance memory b) internal pure returns (bool) {
return a.mantissa > b.mantissa;
}
function gt(Instance memory a, uint256 b) internal pure returns (bool) {
if (b > MAX_INTEGER) return false;
return a.mantissa > b * ONE_MANTISSA;
}
function gte(Instance memory a, Instance memory b) internal pure returns (bool) {
return a.mantissa >= b.mantissa;
}
function gte(Instance memory a, uint256 b) internal pure returns (bool) {
if (b > MAX_INTEGER) return false;
return a.mantissa >= b * ONE_MANTISSA;
}
function lt(Instance memory a, Instance memory b) internal pure returns (bool) {
return a.mantissa < b.mantissa;
}
function lt(Instance memory a, uint256 b) internal pure returns (bool) {
if (b > MAX_INTEGER) return true;
return a.mantissa < b * ONE_MANTISSA;
}
function lte(Instance memory a, Instance memory b) internal pure returns (bool) {
return a.mantissa <= b.mantissa;
}
function lte(Instance memory a, uint256 b) internal pure returns (bool) {
if (b > MAX_INTEGER) return true;
return a.mantissa <= b * ONE_MANTISSA;
}
function isInteger(Instance memory a) internal pure returns (bool) {
return a.mantissa % ONE_MANTISSA == 0;
}
function isPositive(Instance memory a) internal pure returns (bool) {
return a.mantissa > 0;
}
function isZero(Instance memory a) internal pure returns (bool) {
return a.mantissa == 0;
}
function sum(Instance[] memory array) internal pure returns (Instance memory result) {
uint256 length = array.length;
for (uint256 index = 0; index < length; index++) result = add(result, array[index]);
}
function toTuple(Instance memory a)
internal
pure
returns (
uint256 mantissa,
uint256 base,
uint256 exponentiation
)
{
return (a.mantissa, BASE, EXPONENTIATION);
}
}
文件 3 的 18:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 4 的 18:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 5 的 18:Errors.sol
pragma solidity 0.8.19;
library Errors {
error MerkleWhitelist__AddressNotWhitelisted(address wallet);
}
文件 6 的 18:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
文件 7 的 18:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 8 的 18:IStakingPool.sol
pragma solidity 0.8.19;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../StakingPool.sol";
interface IStakingPool {
function cancelUnstaking(uint256 amount) external returns (bool success);
function claim(uint256 amount) external returns (uint256 claimedAmount, uint256 burnedAmount);
function claimFees() external returns (uint256 amount);
function createNewStrategy(
uint256 perBlockReward_,
uint256 startBlockNumber_,
uint256 duration_
)
external
returns (bool success);
function decreasePool(uint256 amount) external returns (bool success);
function increasePool(uint256 amount) external returns (bool success);
function setClaimingFeePercent(uint256 feePercent) external returns (bool success);
function stake(uint256 amount, bytes32[] calldata proof) external returns (uint256 mintedAmount);
function stakeForUser(
address account,
uint256 amount,
bytes32[] calldata proof
)
external
returns (uint256 mintedAmount);
function unstake(uint256 amount) external returns (uint256 unstakedAmount, uint256 burnedAmount);
function update() external returns (bool success);
function withdraw() external returns (bool success);
function setUnstakingTime(uint256 unstakingTime_) external returns (bool success);
function feePool() external view returns (uint256);
function lockedRewards() external view returns (uint256);
function totalStaked() external view returns (uint256);
function totalUnstaked() external view returns (uint256);
function stakingToken() external view returns (IERC20);
function unstakingTime() external view returns (uint256);
function currentStrategy() external view returns (StakingPool.Strategy memory);
function nextStrategy() external view returns (StakingPool.Strategy memory);
function getUnstake(address account) external view returns (StakingPool.Unstake memory result);
function defaultPrice() external view returns (uint256 mantissa, uint256 base, uint256 exponentiation);
function getCurrentStrategyUnlockedRewards() external view returns (uint256 unlocked);
function getUnlockedRewards() external view returns (uint256 unlocked, bool currentStrategyEnded);
function price() external view returns (uint256 mantissa, uint256 base, uint256 exponentiation);
function priceStored() external view returns (uint256 mantissa, uint256 base, uint256 exponentiation);
function calculateUnstake(
address account,
uint256 amount
)
external
view
returns (uint256 unstakedAmount, uint256 burnedAmount);
event Claimed(
address indexed account, uint256 requestedAmount, uint256 claimedAmount, uint256 feeAmount, uint256 burnedAmount
);
event ClaimingFeePercentUpdated(uint256 feePercent);
event CurrentStrategyUpdated(uint256 perBlockReward, uint256 startBlockNumber, uint256 endBlockNumber);
event FeeClaimed(address indexed receiver, uint256 amount);
event Migrated(
address indexed account, uint256 omTokenV1StakeAmount, uint256 stakingPoolV1Reward, uint256 stakingPoolV2Reward
);
event NextStrategyUpdated(uint256 perBlockReward, uint256 startBlockNumber, uint256 endBlockNumber);
event UnstakingTimeUpdated(uint256 unstakingTime);
event NextStrategyRemoved();
event PoolDecreased(uint256 amount);
event PoolIncreased(address indexed payer, uint256 amount);
event PriceUpdated(uint256 mantissa, uint256 base, uint256 exponentiation);
event RewardsUnlocked(uint256 amount);
event Staked(address indexed account, address indexed payer, uint256 stakedAmount, uint256 mintedAmount);
event Unstaked(
address indexed account,
uint256 requestedAmount,
uint256 unstakedAmount,
uint256 burnedAmount,
uint256 applicableAt
);
event UnstakingCanceled(address indexed account, uint256 amount);
event Withdrawed(address indexed account, uint256 amount);
}
文件 9 的 18:IWhitelistMerkle.sol
pragma solidity 0.8.19;
interface IWhitelistMerkle {
function isValidProof(bytes32[] calldata proof, bytes32 leaf) external view returns (bool);
function setNewRootHash(bytes32 _rootHash) external;
}
文件 10 的 18:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
文件 11 的 18:MerkleProof.sol
pragma solidity ^0.8.0;
library MerkleProof {
function verify(
bytes32[] memory proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProof(proof, leaf) == root;
}
function verifyCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32 leaf
) internal pure returns (bool) {
return processProofCalldata(proof, leaf) == root;
}
function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) {
bytes32 computedHash = leaf;
for (uint256 i = 0; i < proof.length; i++) {
computedHash = _hashPair(computedHash, proof[i]);
}
return computedHash;
}
function multiProofVerify(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProof(proof, proofFlags, leaves) == root;
}
function multiProofVerifyCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32 root,
bytes32[] memory leaves
) internal pure returns (bool) {
return processMultiProofCalldata(proof, proofFlags, leaves) == root;
}
function processMultiProof(
bytes32[] memory proof,
bool[] memory proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function processMultiProofCalldata(
bytes32[] calldata proof,
bool[] calldata proofFlags,
bytes32[] memory leaves
) internal pure returns (bytes32 merkleRoot) {
uint256 leavesLen = leaves.length;
uint256 totalHashes = proofFlags.length;
require(leavesLen + proof.length - 1 == totalHashes, "MerkleProof: invalid multiproof");
bytes32[] memory hashes = new bytes32[](totalHashes);
uint256 leafPos = 0;
uint256 hashPos = 0;
uint256 proofPos = 0;
for (uint256 i = 0; i < totalHashes; i++) {
bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++];
bytes32 b = proofFlags[i] ? leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++] : proof[proofPos++];
hashes[i] = _hashPair(a, b);
}
if (totalHashes > 0) {
return hashes[totalHashes - 1];
} else if (leavesLen > 0) {
return leaves[0];
} else {
return proof[0];
}
}
function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) {
return a < b ? _efficientHash(a, b) : _efficientHash(b, a);
}
function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
assembly {
mstore(0x00, a)
mstore(0x20, b)
value := keccak256(0x00, 0x40)
}
}
}
文件 12 的 18:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_transferOwnership(_msgSender());
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 13 的 18:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
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 {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
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) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, 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));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 14 的 18:StakingErrors.sol
pragma solidity 0.8.19;
library StakingErrors {
error StakingPool__StakerNotWhitelisted(address staker);
}
文件 15 的 18:StakingPool.sol
pragma solidity 0.8.19;
pragma experimental ABIEncoderV2;
import "./interfaces/IStakingPool.sol";
import "./libs/StakingErrors.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@whitelist-merkle/Whitelist.sol";
import "solowei/AttoDecimal.sol";
import "solowei/TwoStageOwnable.sol";
contract StakingPool is IStakingPool, ERC20, TwoStageOwnable {
using SafeERC20 for IERC20;
using AttoDecimal for AttoDecimal.Instance;
struct Strategy {
uint256 endBlockNumber;
uint256 perBlockReward;
uint256 startBlockNumber;
}
struct Unstake {
uint256 amount;
uint256 applicableAt;
}
Whitelist public whitelist;
uint256 public constant MIN_STAKE_BALANCE = 10 ** 18;
uint256 public claimingFeePercent;
uint256 public lastUpdateBlockNumber;
uint256 private _feePool;
uint256 private _lockedRewards;
uint256 private _totalStaked;
uint256 private _totalUnstaked;
uint256 private _unstakingTime;
IERC20 private _stakingToken;
AttoDecimal.Instance private _defaultPrice;
AttoDecimal.Instance private _price;
Strategy private _currentStrategy;
Strategy private _nextStrategy;
mapping(address => Unstake) private _unstakes;
constructor(
string memory syntheticTokenName,
string memory syntheticTokenSymbol,
IERC20 stakingToken_,
address owner_,
address whitelistAddress_,
uint256 claimingFeePercent_,
uint256 perBlockReward_,
uint256 startBlockNumber_,
uint256 duration_,
uint256 unstakingTime_,
uint256 defaultPriceMantissa
)
TwoStageOwnable(owner_)
ERC20(syntheticTokenName, syntheticTokenSymbol)
{
_defaultPrice = AttoDecimal.Instance(defaultPriceMantissa);
_stakingToken = stakingToken_;
_setClaimingFeePercent(claimingFeePercent_);
_validateStrategyParameters(perBlockReward_, startBlockNumber_, duration_);
_setUnstakingTime(unstakingTime_);
_setCurrentStrategy(perBlockReward_, startBlockNumber_, startBlockNumber_ + duration_);
lastUpdateBlockNumber = getBlockNumber();
_price = _defaultPrice;
whitelist = Whitelist(whitelistAddress_);
}
function cancelUnstaking(uint256 amount) external onlyPositiveAmount(amount) returns (bool success) {
_update();
address caller = msg.sender;
Unstake storage unstake_ = _unstakes[caller];
uint256 unstakingAmount = unstake_.amount;
require(unstakingAmount >= amount, "Not enough unstaked balance");
uint256 stakedAmount = _price.mul(balanceOf(caller)).floor();
require(stakedAmount + amount >= MIN_STAKE_BALANCE, "Stake balance lt min stake");
uint256 synthAmount = AttoDecimal.div(amount, _price).floor();
_mint(caller, synthAmount);
_totalStaked = _totalStaked + amount;
_totalUnstaked = _totalUnstaked - amount;
unstake_.amount = unstakingAmount - amount;
emit Staked(caller, address(0), amount, synthAmount);
emit UnstakingCanceled(caller, amount);
return true;
}
function claim(uint256 amount)
external
onlyPositiveAmount(amount)
returns (uint256 claimedAmount, uint256 burnedAmount)
{
_update();
address caller = msg.sender;
(claimedAmount, burnedAmount) = _calculateUnstake(caller, amount, _price);
uint256 fee = (claimedAmount * claimingFeePercent) / 100;
_burn(caller, burnedAmount);
_totalStaked = _totalStaked - claimedAmount;
claimedAmount = claimedAmount - fee;
_feePool = _feePool + fee;
emit Claimed(caller, amount, claimedAmount, fee, burnedAmount);
_stakingToken.safeTransfer(caller, claimedAmount);
}
function claimFees() external onlyOwner returns (uint256 amount) {
require(_feePool > 0, "No fees");
amount = _feePool;
_feePool = 0;
emit FeeClaimed(owner(), amount);
_stakingToken.safeTransfer(owner(), amount);
}
function createNewStrategy(
uint256 perBlockReward_,
uint256 startBlockNumber_,
uint256 duration_
)
public
onlyOwner
returns (bool success)
{
_update();
_validateStrategyParameters(perBlockReward_, startBlockNumber_, duration_);
uint256 endBlockNumber = startBlockNumber_ + duration_;
Strategy memory strategy = Strategy({
perBlockReward: perBlockReward_,
startBlockNumber: startBlockNumber_,
endBlockNumber: endBlockNumber
});
if (_currentStrategy.startBlockNumber > getBlockNumber()) {
delete _nextStrategy;
emit NextStrategyRemoved();
_currentStrategy = strategy;
emit CurrentStrategyUpdated(perBlockReward_, startBlockNumber_, endBlockNumber);
} else {
emit NextStrategyUpdated(perBlockReward_, startBlockNumber_, endBlockNumber);
_nextStrategy = strategy;
if (_currentStrategy.endBlockNumber > startBlockNumber_) {
_currentStrategy.endBlockNumber = startBlockNumber_;
emit CurrentStrategyUpdated(
_currentStrategy.perBlockReward, _currentStrategy.startBlockNumber, startBlockNumber_
);
}
}
return true;
}
function decreasePool(uint256 amount) external onlyPositiveAmount(amount) onlyOwner returns (bool success) {
_update();
if (_lockedRewards >= amount) {
_lockedRewards = _lockedRewards - amount;
} else {
amount = _lockedRewards;
_lockedRewards = 0;
}
emit PoolDecreased(amount);
_stakingToken.safeTransfer(owner(), amount);
return true;
}
function increasePool(uint256 amount) external onlyPositiveAmount(amount) returns (bool success) {
_update();
address payer = msg.sender;
_lockedRewards = _lockedRewards + amount;
emit PoolIncreased(payer, amount);
_stakingToken.safeTransferFrom(payer, address(this), amount);
return true;
}
function setClaimingFeePercent(uint256 feePercent) external onlyOwner returns (bool success) {
_setClaimingFeePercent(feePercent);
return true;
}
function stake(
uint256 amount,
bytes32[] calldata proof
)
external
onlyPositiveAmount(amount)
returns (uint256 mintedAmount)
{
if (!whitelist.isValidProof(proof, keccak256(abi.encodePacked(msg.sender)))) {
revert StakingErrors.StakingPool__StakerNotWhitelisted(msg.sender);
}
return _stake(msg.sender, msg.sender, amount);
}
function stakeForUser(
address account,
uint256 amount,
bytes32[] calldata proof
)
external
onlyPositiveAmount(amount)
returns (uint256 mintedAmount)
{
if (!whitelist.isValidProof(proof, keccak256(abi.encodePacked(account)))) {
revert StakingErrors.StakingPool__StakerNotWhitelisted(account);
}
return _stake(account, msg.sender, amount);
}
function unstake(uint256 amount)
external
onlyPositiveAmount(amount)
returns (uint256 unstakedAmount, uint256 burnedAmount)
{
address caller = msg.sender;
_update();
(unstakedAmount, burnedAmount) = _calculateUnstake(caller, amount, _price);
_burn(caller, burnedAmount);
_totalStaked = _totalStaked - unstakedAmount;
_totalUnstaked = _totalUnstaked + unstakedAmount;
Unstake storage unstake_ = _unstakes[caller];
unstake_.amount = unstake_.amount + unstakedAmount;
unstake_.applicableAt = getTimestamp() + _unstakingTime;
emit Unstaked(caller, amount, unstakedAmount, burnedAmount, unstake_.applicableAt);
}
function update() external returns (bool success) {
_update();
return true;
}
function withdraw() external returns (bool success) {
address caller = msg.sender;
Unstake storage unstake_ = _unstakes[caller];
uint256 amount = unstake_.amount;
require(amount > 0, "Not unstaked");
require(unstake_.applicableAt <= getTimestamp(), "Not released at");
delete _unstakes[caller];
_totalUnstaked = _totalUnstaked - amount;
emit Withdrawed(caller, amount);
_stakingToken.safeTransfer(caller, amount);
return true;
}
function setUnstakingTime(uint256 unstakingTime_) external onlyOwner returns (bool success) {
_setUnstakingTime(unstakingTime_);
return true;
}
function _getStrategyUnlockedRewards(Strategy memory strategy_) internal view returns (uint256 unlocked) {
uint256 currentBlockNumber = getBlockNumber();
if (currentBlockNumber < strategy_.startBlockNumber || currentBlockNumber == lastUpdateBlockNumber) {
return unlocked;
}
uint256 lastRewardedBlockNumber = Math.max(lastUpdateBlockNumber, strategy_.startBlockNumber);
uint256 lastRewardableBlockNumber = Math.min(currentBlockNumber, strategy_.endBlockNumber);
if (lastRewardedBlockNumber < lastRewardableBlockNumber) {
uint256 blocksDiff = lastRewardableBlockNumber - lastRewardedBlockNumber;
unlocked = unlocked + (blocksDiff * strategy_.perBlockReward);
}
}
function _calculateUnstake(
address account,
uint256 amount,
AttoDecimal.Instance memory price_
)
internal
view
returns (uint256 unstakedAmount, uint256 burnedAmount)
{
unstakedAmount = amount;
burnedAmount = AttoDecimal.div(amount, price_).ceil();
uint256 balance = balanceOf(account);
require(burnedAmount > 0, "Too small unstaking amount");
require(balance >= burnedAmount, "Not enough synthetic tokens");
uint256 remainingSyntheticBalance = balance - burnedAmount;
uint256 remainingStake = _price.mul(remainingSyntheticBalance).floor();
if (remainingStake < 10 ** 18) {
burnedAmount = balance;
unstakedAmount = unstakedAmount + remainingStake;
}
}
function _unlockRewardsAndStake() internal {
(uint256 unlocked, bool currentStrategyEnded) = getUnlockedRewards();
if (currentStrategyEnded) {
_currentStrategy = _nextStrategy;
emit NextStrategyRemoved();
if (_currentStrategy.endBlockNumber != 0) {
emit CurrentStrategyUpdated(
_currentStrategy.perBlockReward, _currentStrategy.startBlockNumber, _currentStrategy.endBlockNumber
);
}
delete _nextStrategy;
}
unlocked = Math.min(unlocked, _lockedRewards);
if (unlocked > 0) {
emit RewardsUnlocked(unlocked);
_lockedRewards = _lockedRewards - unlocked;
_totalStaked = _totalStaked + unlocked;
}
lastUpdateBlockNumber = getBlockNumber();
}
function _update() internal {
if (getBlockNumber() <= lastUpdateBlockNumber) return;
_unlockRewardsAndStake();
_updatePrice();
}
function _updatePrice() internal {
uint256 totalStaked_ = _totalStaked;
uint256 totalSupply_ = totalSupply();
if (totalSupply_ == 0) _price = _defaultPrice;
else _price = AttoDecimal.div(totalStaked_, totalSupply_);
emit PriceUpdated(_price.mantissa, AttoDecimal.BASE, AttoDecimal.EXPONENTIATION);
}
function _validateStrategyParameters(
uint256 perBlockReward,
uint256 startBlockNumber,
uint256 duration
)
internal
view
{
require(duration > 0, "Duration is zero");
require(startBlockNumber >= getBlockNumber(), "Start block number lt current");
require(perBlockReward <= 188 * 10 ** 18, "Per block reward overflow");
}
function _setClaimingFeePercent(uint256 feePercent) internal {
require(feePercent >= 0 && feePercent <= 100, "Invalid fee percent");
claimingFeePercent = feePercent;
emit ClaimingFeePercentUpdated(feePercent);
}
function _setUnstakingTime(uint256 unstakingTime_) internal {
_unstakingTime = unstakingTime_;
emit UnstakingTimeUpdated(unstakingTime_);
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal override {
_update();
string memory errorText = "Minimal stake balance should be more or equal to 1 token";
if (from != address(0)) {
uint256 fromNewBalance = _price.mul(balanceOf(from) - amount).floor();
require(fromNewBalance >= MIN_STAKE_BALANCE || fromNewBalance == 0, errorText);
}
if (to != address(0)) {
require(_price.mul(balanceOf(to) + amount).floor() >= MIN_STAKE_BALANCE, errorText);
}
}
function _setCurrentStrategy(uint256 perBlockReward_, uint256 startBlockNumber_, uint256 endBlockNumber_) private {
_currentStrategy = Strategy({
perBlockReward: perBlockReward_,
startBlockNumber: startBlockNumber_,
endBlockNumber: endBlockNumber_
});
emit CurrentStrategyUpdated(perBlockReward_, startBlockNumber_, endBlockNumber_);
}
function _stake(address staker, address payer, uint256 amount) private returns (uint256 mintedAmount) {
_update();
mintedAmount = AttoDecimal.div(amount, _price).floor();
require(mintedAmount > 0, "Too small staking amount");
_mint(staker, mintedAmount);
_totalStaked = _totalStaked + amount;
emit Staked(staker, payer, amount, mintedAmount);
_stakingToken.safeTransferFrom(payer, address(this), amount);
}
modifier onlyPositiveAmount(uint256 amount) {
require(amount > 0, "Amount is not positive");
_;
}
function getBlockNumber() internal view virtual returns (uint256) {
return block.number;
}
function getTimestamp() internal view virtual returns (uint256) {
return block.timestamp;
}
function feePool() public view returns (uint256) {
return _feePool;
}
function lockedRewards() public view returns (uint256) {
return _lockedRewards;
}
function totalStaked() public view returns (uint256) {
return _totalStaked;
}
function totalUnstaked() public view returns (uint256) {
return _totalUnstaked;
}
function stakingToken() public view returns (IERC20) {
return _stakingToken;
}
function unstakingTime() public view returns (uint256) {
return _unstakingTime;
}
function currentStrategy() public view returns (Strategy memory) {
return _currentStrategy;
}
function nextStrategy() public view returns (Strategy memory) {
return _nextStrategy;
}
function getUnstake(address account) public view returns (Unstake memory result) {
result = _unstakes[account];
}
function defaultPrice() external view returns (uint256 mantissa, uint256 base, uint256 exponentiation) {
return _defaultPrice.toTuple();
}
function getCurrentStrategyUnlockedRewards() public view returns (uint256 unlocked) {
unlocked = _getStrategyUnlockedRewards(_currentStrategy);
}
function getUnlockedRewards() public view returns (uint256 unlocked, bool currentStrategyEnded) {
unlocked = _getStrategyUnlockedRewards(_currentStrategy);
if (getBlockNumber() >= _currentStrategy.endBlockNumber) {
currentStrategyEnded = true;
if (_nextStrategy.endBlockNumber != 0) unlocked = unlocked + _getStrategyUnlockedRewards(_nextStrategy);
}
}
function price() public view returns (uint256 mantissa, uint256 base, uint256 exponentiation) {
(uint256 unlocked,) = getUnlockedRewards();
uint256 totalStaked_ = _totalStaked;
uint256 totalSupply_ = totalSupply();
AttoDecimal.Instance memory result = _defaultPrice;
if (totalSupply_ > 0) result = AttoDecimal.div(totalStaked_ + unlocked, totalSupply_);
return result.toTuple();
}
function priceStored() public view returns (uint256 mantissa, uint256 base, uint256 exponentiation) {
return _price.toTuple();
}
function calculateUnstake(
address account,
uint256 amount
)
public
view
returns (uint256 unstakedAmount, uint256 burnedAmount)
{
(uint256 mantissa_,,) = price();
return _calculateUnstake(account, amount, AttoDecimal.Instance(mantissa_));
}
}
文件 16 的 18:TwoStageOwnable.sol
pragma solidity ^0.8.6;
abstract contract TwoStageOwnable {
address private _nominatedOwner;
address private _owner;
function nominatedOwner() public view returns (address) {
return _nominatedOwner;
}
function owner() public view returns (address) {
return _owner;
}
event OwnerChanged(address indexed newOwner);
event OwnerNominated(address indexed nominatedOwner);
constructor(address owner_) {
require(owner_ != address(0), "Owner is zero");
_setOwner(owner_);
}
function acceptOwnership() external returns (bool success) {
require(msg.sender == _nominatedOwner, "Not nominated to ownership");
_setOwner(_nominatedOwner);
return true;
}
function nominateNewOwner(address owner_) external onlyOwner returns (bool success) {
_nominateNewOwner(owner_);
return true;
}
modifier onlyOwner {
require(msg.sender == _owner, "Not owner");
_;
}
function _nominateNewOwner(address owner_) internal {
if (_nominatedOwner == owner_) return;
require(_owner != owner_, "Already owner");
_nominatedOwner = owner_;
emit OwnerNominated(owner_);
}
function _setOwner(address newOwner) internal {
if (_owner == newOwner) return;
_owner = newOwner;
_nominatedOwner = address(0);
emit OwnerChanged(newOwner);
}
}
文件 17 的 18:Whitelist.sol
pragma solidity 0.8.19;
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./interfaces/IWhitelistMerkle.sol";
import "./libs/Errors.sol";
contract Whitelist is IWhitelistMerkle, Ownable {
bytes32 public rootHash;
constructor(bytes32 _rootHash) {
rootHash = _rootHash;
}
function isValidProof(bytes32[] calldata proof, bytes32 leaf) external view returns (bool) {
return MerkleProof.verifyCalldata(proof, rootHash, leaf);
}
function setNewRootHash(bytes32 _rootHash) external onlyOwner {
rootHash = _rootHash;
}
function renounceOwnership() public override onlyOwner {
revert("Can't renounceOwnership here");
}
}
文件 18 的 18:draft-IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
{
"compilationTarget": {
"StakingPool/src/StakingPool.sol": "StakingPool"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin-06/=lib/openzeppelin-contracts-06/",
":@openzeppelin/=lib/openzeppelin-contracts/",
":@whitelist-merkle/=WhitelistMerkle/src/",
":@whitelist/=Whitelist/src/",
":ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
":fixedswap-enhanced/=FixedSwapEnhanced/src/",
":fixedswap/=FixedSwap/src/",
":forge-std/=lib/openzeppelin-contracts/lib/forge-std/src/",
":issuance/=IssuanceToken/src/",
":openzeppelin-contracts-06/=lib/openzeppelin-contracts-06/contracts/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":solowei-06/=lib/solowei-06/contracts/",
":solowei/=lib/solowei/contracts/"
]
}
[{"inputs":[{"internalType":"string","name":"syntheticTokenName","type":"string"},{"internalType":"string","name":"syntheticTokenSymbol","type":"string"},{"internalType":"contract IERC20","name":"stakingToken_","type":"address"},{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"whitelistAddress_","type":"address"},{"internalType":"uint256","name":"claimingFeePercent_","type":"uint256"},{"internalType":"uint256","name":"perBlockReward_","type":"uint256"},{"internalType":"uint256","name":"startBlockNumber_","type":"uint256"},{"internalType":"uint256","name":"duration_","type":"uint256"},{"internalType":"uint256","name":"unstakingTime_","type":"uint256"},{"internalType":"uint256","name":"defaultPriceMantissa","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"StakingPool__StakerNotWhitelisted","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"claimedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnedAmount","type":"uint256"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"feePercent","type":"uint256"}],"name":"ClaimingFeePercentUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"perBlockReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startBlockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlockNumber","type":"uint256"}],"name":"CurrentStrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeeClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"omTokenV1StakeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingPoolV1Reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stakingPoolV2Reward","type":"uint256"}],"name":"Migrated","type":"event"},{"anonymous":false,"inputs":[],"name":"NextStrategyRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"perBlockReward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startBlockNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endBlockNumber","type":"uint256"}],"name":"NextStrategyUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nominatedOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PoolDecreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PoolIncreased","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"mantissa","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"base","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"exponentiation","type":"uint256"}],"name":"PriceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardsUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"payer","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintedAmount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"requestedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unstakedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"burnedAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"applicableAt","type":"uint256"}],"name":"Unstaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"UnstakingCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"unstakingTime","type":"uint256"}],"name":"UnstakingTimeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawed","type":"event"},{"inputs":[],"name":"MIN_STAKE_BALANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateUnstake","outputs":[{"internalType":"uint256","name":"unstakedAmount","type":"uint256"},{"internalType":"uint256","name":"burnedAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"cancelUnstaking","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claim","outputs":[{"internalType":"uint256","name":"claimedAmount","type":"uint256"},{"internalType":"uint256","name":"burnedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimFees","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimingFeePercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"perBlockReward_","type":"uint256"},{"internalType":"uint256","name":"startBlockNumber_","type":"uint256"},{"internalType":"uint256","name":"duration_","type":"uint256"}],"name":"createNewStrategy","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentStrategy","outputs":[{"components":[{"internalType":"uint256","name":"endBlockNumber","type":"uint256"},{"internalType":"uint256","name":"perBlockReward","type":"uint256"},{"internalType":"uint256","name":"startBlockNumber","type":"uint256"}],"internalType":"struct StakingPool.Strategy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decreasePool","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultPrice","outputs":[{"internalType":"uint256","name":"mantissa","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint256","name":"exponentiation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feePool","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentStrategyUnlockedRewards","outputs":[{"internalType":"uint256","name":"unlocked","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getUnlockedRewards","outputs":[{"internalType":"uint256","name":"unlocked","type":"uint256"},{"internalType":"bool","name":"currentStrategyEnded","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getUnstake","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"applicableAt","type":"uint256"}],"internalType":"struct StakingPool.Unstake","name":"result","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"increasePool","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastUpdateBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextStrategy","outputs":[{"components":[{"internalType":"uint256","name":"endBlockNumber","type":"uint256"},{"internalType":"uint256","name":"perBlockReward","type":"uint256"},{"internalType":"uint256","name":"startBlockNumber","type":"uint256"}],"internalType":"struct StakingPool.Strategy","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"nominateNewOwner","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price","outputs":[{"internalType":"uint256","name":"mantissa","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint256","name":"exponentiation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceStored","outputs":[{"internalType":"uint256","name":"mantissa","type":"uint256"},{"internalType":"uint256","name":"base","type":"uint256"},{"internalType":"uint256","name":"exponentiation","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"feePercent","type":"uint256"}],"name":"setClaimingFeePercent","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unstakingTime_","type":"uint256"}],"name":"setUnstakingTime","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"stake","outputs":[{"internalType":"uint256","name":"mintedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"stakeForUser","outputs":[{"internalType":"uint256","name":"mintedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalUnstaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[{"internalType":"uint256","name":"unstakedAmount","type":"uint256"},{"internalType":"uint256","name":"burnedAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unstakingTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"update","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"whitelist","outputs":[{"internalType":"contract Whitelist","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdraw","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]