编译器
0.8.18+commit.87f61d96
文件 1 的 28: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 的 28: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;
}
}
文件 3 的 28:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 4 的 28:IAccessControlHolder.sol
pragma solidity 0.8.18;
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
interface IAccessControlHolder {
function acl() external view returns (IAccessControl);
}
文件 5 的 28:IContractsRepostiory.sol
pragma solidity 0.8.18;
interface IContractsRepostiory {
error ContractDoesNotExist();
error OnlyRepositoryOnwer();
function getContract(bytes32 contractId) external view returns (address);
function tryGetContract(bytes32 contractId) external view returns (address);
function setContract(bytes32 contractId, address contractAddress) external;
}
文件 6 的 28: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 的 28: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);
}
文件 8 的 28:ILinearStaking.sol
pragma solidity 0.8.18;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface ILinearStaking {
error BeforeStakingStart();
error AfterStakingFinish();
error AmountZero();
error RewardBalanceTooSmall();
error NotValidUnlockTimestamp();
error ToEarlyToWithdrawReward();
error TooSmallAmount();
error StartNotValid();
event Staked(address indexed wallet, uint256 amount);
event Unstaked(address indexed wallet, uint256 amount);
event RewardTaken(address indexed wallet, uint256 amount);
event Initialized(
uint256 start,
uint256 duration,
uint256 reward,
uint256 unlockTokensTimestamp
);
function stake(uint256) external;
function unlockTokens(IERC20 token, address _to, uint256 _amount) external;
function withdraw(uint256) external payable;
function earned(address _account) external view returns (uint256);
function start() external view returns (uint256);
function finishAt() external view returns (uint256);
function stakingToken() external view returns (IERC20);
function rewardToken() external view returns (IERC20);
function totalSupply() external view returns (uint256);
function duration() external view returns (uint256);
function balanceOf(address) external view returns (uint256);
function rewardPerToken() external view returns (uint256);
function unlockTokensTimestamp() external view returns (uint256);
}
文件 9 的 28:ISpartaStaking.sol
pragma solidity 0.8.18;
interface ISpartaStaking {
error RewardBalanceTooSmall();
error BeforeStakingStart();
error AfterStakingFinish();
error TokensAlreadyClaimed();
error RoundDoesNotExist();
error BeforeReleaseTime();
error NotValidUnlockTimestamp();
error ToEarlyToWithdrawReward();
error StartNotValid();
error MinimalUnstakingPeriod();
error CannotUnstake();
error CurrentImplementation();
struct TokensToClaim {
bool taken;
uint256 release;
uint256 value;
}
event Staked(address indexed wallet, uint256 value);
event Unstaked(
address indexed wallet,
uint256 tokensAmount,
uint256 tokensToClaim,
uint256 duration
);
event TokensClaimed(
address indexed wallet,
uint256 indexed roundId,
uint256 tokensToClaimid
);
event RewardTaken(address indexed wallet, uint256 amount);
event Initialized(
uint256 start,
uint256 duration,
uint256 reward,
uint256 unlockTokensTimestamp
);
event MovedToNextImplementation(
address indexed by,
uint256 balance,
uint256 reward
);
function finishAt() external view returns (uint256);
function stake(uint256 amount) external;
function stakeAs(address wallet, uint256 amount) external;
function unlockTokens(address to, uint256 amount) external;
function unlockTokensTimestamp() external view returns (uint256);
}
文件 10 的 28:IUniswapV2Callee.sol
pragma solidity 0.8.18;
interface IUniswapV2Callee {
function uniswapV2Call(
address sender,
uint amount0,
uint amount1,
bytes calldata data
) external;
}
文件 11 的 28:IUniswapV2ERC20.sol
pragma solidity 0.8.18;
interface IUniswapV2ERC20 {
event Approval(address indexed owner, address indexed spender, uint value);
event Transfer(address indexed from, address indexed to, uint value);
function name() external pure returns (string memory);
function symbol() external pure returns (string memory);
function decimals() external pure returns (uint8);
function totalSupply() external view returns (uint);
function balanceOf(address owner) external view returns (uint);
function allowance(
address owner,
address spender
) external view returns (uint);
function approve(address spender, uint value) external returns (bool);
function transfer(address to, uint value) external returns (bool);
function transferFrom(
address from,
address to,
uint value
) external returns (bool);
function DOMAIN_SEPARATOR() external view returns (bytes32);
function PERMIT_TYPEHASH() external pure returns (bytes32);
function nonces(address owner) external view returns (uint);
function permit(
address owner,
address spender,
uint value,
uint deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
}
文件 12 的 28:IUniswapV2Factory.sol
pragma solidity 0.8.18;
interface IUniswapV2Factory {
error IdenticalAddress();
error ZeroAddress();
error PairAlreadyExists();
error OnlyFeeToSetter();
event PairCreated(
address indexed token0,
address indexed token1,
address pair,
uint
);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(
address tokenA,
address tokenB
) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(
address tokenA,
address tokenB
) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
文件 13 的 28:IUniswapV2Pair.sol
pragma solidity 0.8.18;
import {IUniswapV2ERC20} from "./IUniswapV2ERC20.sol";
interface IUniswapV2Pair is IUniswapV2ERC20 {
event Mint(address indexed sender, uint amount0, uint amount1);
event Burn(
address indexed sender,
uint amount0,
uint amount1,
address indexed to
);
event Swap(
address indexed sender,
uint amount0In,
uint amount1In,
uint amount0Out,
uint amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
function MINIMUM_LIQUIDITY() external pure returns (uint);
function factory() external view returns (address);
function token0() external view returns (address);
function token1() external view returns (address);
function getReserves()
external
view
returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
function price0CumulativeLast() external view returns (uint);
function price1CumulativeLast() external view returns (uint);
function kLast() external view returns (uint);
function mint(address to) external returns (uint liquidity);
function burn(address to) external returns (uint amount0, uint amount1);
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data
) external;
function skim(address to) external;
function sync() external;
function initialize(address, address) external;
}
文件 14 的 28:IWithFees.sol
pragma solidity 0.8.18;
interface IWithFees {
error OnlyFeesManagerAccess();
error OnlyWithFees();
error ETHTransferFailed();
function treasury() external view returns (address);
function fees() external view returns (uint256);
function transfer() external;
}
文件 15 的 28:LinearStaking.sol
pragma solidity 0.8.18;
import {ILinearStaking} from "./interfaces/ILinearStaking.sol";
import {IAccessControlHolder} from "../IAccessControlHolder.sol";
import {ToInitialize} from "../ToInitialize.sol";
import {WithFees} from "../WithFees.sol";
import {ZeroAmountGuard} from "../ZeroAmountGuard.sol";
import {ZeroAddressGuard} from "../ZeroAddressGuard.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
contract LinearStaking is
ILinearStaking,
ToInitialize,
Ownable,
WithFees,
ZeroAmountGuard,
ZeroAddressGuard
{
using SafeERC20 for IERC20;
uint256 constant UNLOCK_TIMESTAMP_MINIMUM_DIFF = 30 days;
IERC20 public immutable override stakingToken;
IERC20 public immutable override rewardToken;
uint256 public override totalSupply;
uint256 public start;
uint256 public override duration;
uint256 public updatedAt;
uint256 public rewardRate;
uint256 public rewardPerTokenStored;
uint256 public unlockTokensTimestamp;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) public override balanceOf;
modifier updateReward(address _account) {
rewardPerTokenStored = rewardPerToken();
updatedAt = lastTimeRewardApplicable();
if (_account != address(0)) {
rewards[_account] = earned(_account);
userRewardPerTokenPaid[_account] = rewardPerTokenStored;
}
_;
}
modifier isOngoing() {
if (block.timestamp < start) {
revert BeforeStakingStart();
}
if (finishAt() < block.timestamp) {
revert AfterStakingFinish();
}
_;
}
constructor(
IERC20 stakingToken_,
IERC20 rewardToken_,
IAccessControl acl_,
address treasury_,
uint256 fees_
) Ownable() WithFees(acl_, treasury_, fees_) {
stakingToken = stakingToken_;
rewardToken = rewardToken_;
}
function initialize(
uint256 amount_,
uint256 duration_,
uint256 start_,
uint256 unlockTokensTimestamp_
)
external
notInitialized
onlyOwner
notZeroAmount(amount_)
notZeroAmount(duration_)
{
if (rewardToken.balanceOf(address(this)) < amount_) {
revert RewardBalanceTooSmall();
}
if (block.timestamp > start_) {
revert StartNotValid();
}
duration = duration_;
rewardRate = amount_ / duration_;
start = start_;
updatedAt = block.timestamp;
unlockTokensTimestamp = unlockTokensTimestamp_;
if (
finishAt() + UNLOCK_TIMESTAMP_MINIMUM_DIFF > unlockTokensTimestamp_
) {
revert NotValidUnlockTimestamp();
}
initialized = true;
emit Initialized(start_, duration_, amount_, unlockTokensTimestamp_);
}
function unlockTokens(
IERC20 token,
address to,
uint256 amount
)
external
notZeroAmount(amount)
notZeroAddress(to)
isInitialized
onlyOwner
{
if (block.timestamp < unlockTokensTimestamp) {
revert ToEarlyToWithdrawReward();
}
token.safeTransfer(to, amount);
}
function stake(
uint256 amount
) external override isInitialized isOngoing updateReward(msg.sender) {
stakingToken.safeTransferFrom(msg.sender, address(this), amount);
balanceOf[msg.sender] += amount;
totalSupply += amount;
emit Staked(msg.sender, amount);
}
function withdraw(
uint256 amount
)
external
payable
override
onlyWithFees
isInitialized
notZeroAmount(amount)
updateReward(msg.sender)
{
stakingToken.safeTransfer(msg.sender, amount);
balanceOf[msg.sender] -= amount;
totalSupply -= amount;
emit Unstaked(msg.sender, amount);
}
function getReward()
external
payable
virtual
isInitialized
onlyWithFees
updateReward(msg.sender)
{
uint256 reward = rewards[msg.sender];
if (reward == 0) {
revert AmountZero();
}
rewards[msg.sender] = 0;
rewardToken.safeTransfer(msg.sender, reward);
emit RewardTaken(msg.sender, reward);
}
function rewardPerToken() public view override returns (uint) {
if (totalSupply == 0 || block.timestamp < start) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored +
(rewardRate * (lastTimeRewardApplicable() - updatedAt) * 1e18) /
totalSupply;
}
function earned(address _account) public view override returns (uint256) {
return
((balanceOf[_account] *
((rewardPerToken() - userRewardPerTokenPaid[_account]))) /
1e18) + rewards[_account];
}
function lastTimeRewardApplicable() public view returns (uint256) {
return _min(finishAt(), block.timestamp);
}
function finishAt() public view override returns (uint256) {
return start + duration;
}
function _min(uint x, uint y) private pure returns (uint256) {
return x <= y ? x : y;
}
}
文件 16 的 28:LpLinearStaking.sol
pragma solidity 0.8.18;
import {SpartaDexPair} from "../dex/core/SpartaDexPair.sol";
import {LinearStaking} from "./LinearStaking.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
contract LpLinearStaking is LinearStaking {
constructor(
SpartaDexPair _lpToken,
IERC20 _reward,
IAccessControl _acl,
address _treasury,
uint256 _value
)
LinearStaking(
IERC20(address(_lpToken)),
_reward,
_acl,
_treasury,
_value
)
{}
}
文件 17 的 28:Math.sol
pragma solidity 0.8.18;
library Math {
function min(uint x, uint y) internal pure returns (uint z) {
z = x < y ? x : y;
}
function sqrt(uint y) internal pure returns (uint z) {
if (y > 3) {
z = y;
uint x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
文件 18 的 28: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);
}
}
文件 19 的 28:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/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 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
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");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
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");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 20 的 28:SafeMath.sol
pragma solidity 0.8.18;
library SafeMath {
function add(uint x, uint y) internal pure returns (uint z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint x, uint y) internal pure returns (uint z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint x, uint y) internal pure returns (uint z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
function div(uint x, uint y) internal pure returns (uint) {
require(y != 0, "ds-math-div-zero");
return x / y;
}
}
文件 21 的 28:SpartaDexERC20.sol
pragma solidity 0.8.18;
import {IUniswapV2ERC20} from "./interfaces/IUniswapV2ERC20.sol";
import {SafeMath} from "./libraries/SafeMath.sol";
contract SpartaDexERC20 is IUniswapV2ERC20 {
string public constant override name = "SpartaDexERC20";
string public constant override symbol = "SRTDX";
uint8 public constant override decimals = 18;
uint public override totalSupply;
mapping(address => uint) public override balanceOf;
mapping(address => mapping(address => uint)) public override allowance;
bytes32 public override DOMAIN_SEPARATOR;
bytes32 public constant override PERMIT_TYPEHASH =
0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint) public override nonces;
constructor() {
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name)),
keccak256(bytes("1")),
_chainId(),
address(this)
)
);
}
function _chainId() internal view returns (uint256 chainId_) {
assembly {
chainId_ := chainid()
}
}
function _mint(address to, uint value) internal {
totalSupply += value;
balanceOf[to] += value;
emit Transfer(address(0), to, value);
}
function _burn(address from, uint value) internal {
balanceOf[from] -= value;
totalSupply -= value;
emit Transfer(from, address(0), value);
}
function _approve(address owner, address spender, uint value) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(address from, address to, uint value) private {
balanceOf[from] -= value;
balanceOf[to] += value;
emit Transfer(from, to, value);
}
function approve(
address spender,
uint value
) external override returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint value) external override returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(
address from,
address to,
uint value
) external override returns (bool) {
if (allowance[from][msg.sender] != type(uint).max) {
allowance[from][msg.sender] -= value;
}
_transfer(from, to, value);
return true;
}
function permit(
address owner,
address spender,
uint value,
uint deadline,
uint8 v,
bytes32 r,
bytes32 s
) external override {
require(deadline >= block.timestamp, "UniswapV2: EXPIRED");
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(
recoveredAddress != address(0) && recoveredAddress == owner,
"UniswapV2: INVALID_SIGNATURE"
);
_approve(owner, spender, value);
}
}
文件 22 的 28:SpartaDexPair.sol
pragma solidity 0.8.18;
import {IUniswapV2Pair} from "./interfaces/IUniswapV2Pair.sol";
import {SpartaDexERC20} from "./SpartaDexERC20.sol";
import {Math} from "./libraries/Math.sol";
import {SafeMath} from "./libraries/SafeMath.sol";
import {UQ112x112} from "./libraries/UQ112x112.sol";
import {IUniswapV2Factory} from "./interfaces/IUniswapV2Factory.sol";
import {IUniswapV2Callee} from "./interfaces/IUniswapV2Callee.sol";
contract SpartaDexPair is IUniswapV2Pair, SpartaDexERC20 {
using SafeMath for uint;
using UQ112x112 for uint224;
uint public constant override MINIMUM_LIQUIDITY = 10 ** 3;
bytes4 private constant SELECTOR =
bytes4(keccak256(bytes("transfer(address,uint256)")));
address public override factory;
address public override token0;
address public override token1;
uint112 private reserve0;
uint112 private reserve1;
uint32 private blockTimestampLast;
uint public override price0CumulativeLast;
uint public override price1CumulativeLast;
uint public override kLast;
uint private unlocked = 1;
modifier lock() {
require(unlocked == 1, "UniswapV2: LOCKED");
unlocked = 0;
_;
unlocked = 1;
}
function getReserves()
public
view
override
returns (
uint112 _reserve0,
uint112 _reserve1,
uint32 _blockTimestampLast
)
{
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
function _safeTransfer(address token, address to, uint value) private {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(SELECTOR, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"UniswapV2: TRANSFER_FAILED"
);
}
constructor() {
factory = msg.sender;
}
function initialize(address _token0, address _token1) external override {
require(msg.sender == factory, "UniswapV2: FORBIDDEN");
token0 = _token0;
token1 = _token1;
}
function _update(
uint balance0,
uint balance1,
uint112 _reserve0,
uint112 _reserve1
) private {
require(
balance0 <= type(uint112).max && balance1 <= type(uint112).max,
"UniswapV2: OVERFLOW"
);
uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32);
uint32 timeElapsed = blockTimestamp - blockTimestampLast;
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
price0CumulativeLast +=
uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) *
timeElapsed;
price1CumulativeLast +=
uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) *
timeElapsed;
}
reserve0 = uint112(balance0);
reserve1 = uint112(balance1);
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
function _mintFee(
uint112 _reserve0,
uint112 _reserve1
) private returns (bool feeOn) {
address feeTo = IUniswapV2Factory(factory).feeTo();
feeOn = feeTo != address(0);
uint _kLast = kLast;
if (feeOn) {
if (_kLast != 0) {
uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
uint rootKLast = Math.sqrt(_kLast);
if (rootK > rootKLast) {
uint numerator = totalSupply.mul(rootK.sub(rootKLast));
uint denominator = rootK.mul(5).add(rootKLast);
uint liquidity = numerator / denominator;
if (liquidity > 0) _mint(feeTo, liquidity);
}
}
} else if (_kLast != 0) {
kLast = 0;
}
}
function mint(address to) external override lock returns (uint liquidity) {
(uint112 _reserve0, uint112 _reserve1, ) = getReserves();
uint balance0 = IUniswapV2Pair(token0).balanceOf(address(this));
uint balance1 = IUniswapV2Pair(token1).balanceOf(address(this));
uint amount0 = balance0.sub(_reserve0);
uint amount1 = balance1.sub(_reserve1);
bool feeOn = _mintFee(_reserve0, _reserve1);
uint _totalSupply = totalSupply;
if (_totalSupply == 0) {
liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
_mint(address(0), MINIMUM_LIQUIDITY);
} else {
liquidity = Math.min(
amount0.mul(_totalSupply) / _reserve0,
amount1.mul(_totalSupply) / _reserve1
);
}
require(liquidity > 0, "UniswapV2: INSUFFICIENT_LIQUIDITY_MINTED");
_mint(to, liquidity);
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint(reserve0).mul(reserve1);
emit Mint(msg.sender, amount0, amount1);
}
function burn(
address to
) external override lock returns (uint amount0, uint amount1) {
(uint112 _reserve0, uint112 _reserve1, ) = getReserves();
address _token0 = token0;
address _token1 = token1;
uint balance0 = IUniswapV2Pair(_token0).balanceOf(address(this));
uint balance1 = IUniswapV2Pair(_token1).balanceOf(address(this));
uint liquidity = balanceOf[address(this)];
bool feeOn = _mintFee(_reserve0, _reserve1);
uint _totalSupply = totalSupply;
amount0 = liquidity.mul(balance0) / _totalSupply;
amount1 = liquidity.mul(balance1) / _totalSupply;
require(
amount0 > 0 && amount1 > 0,
"UniswapV2: INSUFFICIENT_LIQUIDITY_BURNED"
);
_burn(address(this), liquidity);
_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);
balance0 = IUniswapV2Pair(_token0).balanceOf(address(this));
balance1 = IUniswapV2Pair(_token1).balanceOf(address(this));
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint(reserve0).mul(reserve1);
emit Burn(msg.sender, amount0, amount1, to);
}
function swap(
uint amount0Out,
uint amount1Out,
address to,
bytes calldata data
) external override lock {
require(
amount0Out > 0 || amount1Out > 0,
"UniswapV2: INSUFFICIENT_OUTPUT_AMOUNT"
);
(uint112 _reserve0, uint112 _reserve1, ) = getReserves();
require(
amount0Out < _reserve0 && amount1Out < _reserve1,
"UniswapV2: INSUFFICIENT_LIQUIDITY"
);
uint balance0;
uint balance1;
{
address _token0 = token0;
address _token1 = token1;
require(to != _token0 && to != _token1, "UniswapV2: INVALID_TO");
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out);
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out);
if (data.length > 0)
IUniswapV2Callee(to).uniswapV2Call(
msg.sender,
amount0Out,
amount1Out,
data
);
balance0 = IUniswapV2Pair(_token0).balanceOf(address(this));
balance1 = IUniswapV2Pair(_token1).balanceOf(address(this));
}
uint amount0In = balance0 > _reserve0 - amount0Out
? balance0 - (_reserve0 - amount0Out)
: 0;
uint amount1In = balance1 > _reserve1 - amount1Out
? balance1 - (_reserve1 - amount1Out)
: 0;
require(
amount0In > 0 || amount1In > 0,
"UniswapV2: INSUFFICIENT_INPUT_AMOUNT"
);
{
uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
require(
balance0Adjusted.mul(balance1Adjusted) >=
uint(_reserve0).mul(_reserve1).mul(1000 ** 2),
"UniswapV2: K"
);
}
_update(balance0, balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
function skim(address to) external override lock {
address _token0 = token0;
address _token1 = token1;
_safeTransfer(
_token0,
to,
IUniswapV2Pair(_token0).balanceOf(address(this)).sub(reserve0)
);
_safeTransfer(
_token1,
to,
IUniswapV2Pair(_token1).balanceOf(address(this)).sub(reserve1)
);
}
function sync() external override lock {
_update(
IUniswapV2Pair(token0).balanceOf(address(this)),
IUniswapV2Pair(token1).balanceOf(address(this)),
reserve0,
reserve1
);
}
}
文件 23 的 28:SpartaRewardLpLinearStaking.sol
pragma solidity 0.8.18;
import {LpLinearStaking, SpartaDexPair, IAccessControl} from "./LpLinearStaking.sol";
import {ISpartaStaking} from "./interfaces/ISpartaStaking.sol";
import {IContractsRepostiory} from "../IContractsRepostiory.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract SpartaRewardLpLinearStaking is LpLinearStaking {
using SafeERC20 for IERC20;
bytes32 constant SPARTA_STAKING_CONTRACT_ID = keccak256("SPARTA_STAKING");
IContractsRepostiory public contractsRepository;
constructor(
SpartaDexPair _lpToken,
IERC20 _sparta,
IAccessControl _acl,
IContractsRepostiory _contractsRepository,
address _treasury,
uint256 _value
) LpLinearStaking(_lpToken, _sparta, _acl, _treasury, _value) {
contractsRepository = _contractsRepository;
}
function getReward()
external
payable
override
isInitialized
onlyWithFees
updateReward(msg.sender)
{
address spartaStakingAddress = contractsRepository.tryGetContract(
SPARTA_STAKING_CONTRACT_ID
);
uint256 reward = rewards[msg.sender];
if (reward == 0) {
revert AmountZero();
}
uint256 toTransfer = reward;
if (spartaStakingAddress != address(0)) {
ISpartaStaking staking = ISpartaStaking(spartaStakingAddress);
toTransfer = (reward * 250000) / 1000000;
uint256 onStaking = reward - toTransfer;
rewardToken.forceApprove(spartaStakingAddress, onStaking);
staking.stakeAs(msg.sender, onStaking);
}
rewards[msg.sender] = 0;
rewardToken.safeTransfer(msg.sender, toTransfer);
emit RewardTaken(msg.sender, toTransfer);
}
}
文件 24 的 28:ToInitialize.sol
pragma solidity 0.8.18;
contract ToInitialize {
error AlreadyInitialized();
error NotInitialized();
bool internal initialized;
modifier isInitialized() {
_isInitialized();
_;
}
function _isInitialized() internal view {
if (!initialized) {
revert NotInitialized();
}
}
modifier notInitialized() {
if (initialized) {
revert AlreadyInitialized();
}
_;
}
}
文件 25 的 28:UQ112x112.sol
pragma solidity 0.8.18;
library UQ112x112 {
uint224 constant Q112 = 2 ** 112;
function encode(uint112 y) internal pure returns (uint224 z) {
z = uint224(y) * Q112;
}
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
z = x / uint224(y);
}
}
文件 26 的 28:WithFees.sol
pragma solidity 0.8.18;
import {IAccessControlHolder, IAccessControl} from "./IAccessControlHolder.sol";
import {IWithFees} from "./IWithFees.sol";
contract WithFees is IAccessControlHolder, IWithFees {
address public immutable override treasury;
uint256 public immutable override fees;
IAccessControl public immutable override acl;
bytes32 public constant FEES_MANAGER = keccak256("FEES_MANAGER");
modifier onlyWithFees() {
if (fees != msg.value) {
revert OnlyWithFees();
}
_;
}
modifier onlyFeesManagerAccess() {
if (!acl.hasRole(FEES_MANAGER, msg.sender)) {
revert OnlyFeesManagerAccess();
}
_;
}
constructor(IAccessControl acl_, address treasury_, uint256 value_) {
acl = acl_;
treasury = treasury_;
fees = value_;
}
function transfer() external onlyFeesManagerAccess {
(bool sent, ) = treasury.call{value: address(this).balance}("");
if (!sent) {
revert ETHTransferFailed();
}
}
}
文件 27 的 28:ZeroAddressGuard.sol
pragma solidity 0.8.18;
contract ZeroAddressGuard {
error ZeroAddress();
modifier notZeroAddress(address _addr) {
_ensureIsNotZeroAddress(_addr);
_;
}
function _ensureIsNotZeroAddress(address _addr) internal pure {
if (_addr == address(0)) {
revert ZeroAddress();
}
}
}
文件 28 的 28:ZeroAmountGuard.sol
pragma solidity 0.8.18;
contract ZeroAmountGuard {
error ZeroAmount();
modifier notZeroAmount(uint256 _amount) {
_ensureIsNotZero(_amount);
_;
}
function _ensureIsNotZero(uint256 _amount) internal pure {
if (_amount == 0) {
revert ZeroAmount();
}
}
}
{
"compilationTarget": {
"contracts/staking/SpartaRewardLpLinearStaking.sol": "SpartaRewardLpLinearStaking"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract SpartaDexPair","name":"_lpToken","type":"address"},{"internalType":"contract IERC20","name":"_sparta","type":"address"},{"internalType":"contract IAccessControl","name":"_acl","type":"address"},{"internalType":"contract IContractsRepostiory","name":"_contractsRepository","type":"address"},{"internalType":"address","name":"_treasury","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AfterStakingFinish","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"AmountZero","type":"error"},{"inputs":[],"name":"BeforeStakingStart","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"NotInitialized","type":"error"},{"inputs":[],"name":"NotValidUnlockTimestamp","type":"error"},{"inputs":[],"name":"OnlyFeesManagerAccess","type":"error"},{"inputs":[],"name":"OnlyWithFees","type":"error"},{"inputs":[],"name":"RewardBalanceTooSmall","type":"error"},{"inputs":[],"name":"StartNotValid","type":"error"},{"inputs":[],"name":"ToEarlyToWithdrawReward","type":"error"},{"inputs":[],"name":"TooSmallAmount","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"inputs":[],"name":"ZeroAmount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"start","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"duration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reward","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"unlockTokensTimestamp","type":"uint256"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardTaken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Staked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"wallet","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstaked","type":"event"},{"inputs":[],"name":"FEES_MANAGER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acl","outputs":[{"internalType":"contract IAccessControl","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractsRepository","outputs":[{"internalType":"contract IContractsRepostiory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"duration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"earned","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"finishAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"uint256","name":"duration_","type":"uint256"},{"internalType":"uint256","name":"start_","type":"uint256"},{"internalType":"uint256","name":"unlockTokensTimestamp_","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lastTimeRewardApplicable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardPerToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardPerTokenStored","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"start","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":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unlockTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unlockTokensTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"updatedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"userRewardPerTokenPaid","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"}]