Source Code
Latest 25 from a total of 159 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Claim Tokens | 16838390 | 303 days ago | IN | 0 S | 0.01229247 | ||||
| Claim Tokens | 16100892 | 306 days ago | IN | 0 S | 0.01085238 | ||||
| Claim Tokens | 16000273 | 306 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15555971 | 308 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15511586 | 309 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15452773 | 309 days ago | IN | 0 S | 0.01053629 | ||||
| Claim Tokens | 15437552 | 309 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15424088 | 309 days ago | IN | 0 S | 0.01098092 | ||||
| Claim Tokens | 15422392 | 309 days ago | IN | 0 S | 0.01110754 | ||||
| Claim Tokens | 15410938 | 309 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15408317 | 309 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15391146 | 309 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15381810 | 309 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15365490 | 309 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15362687 | 309 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15353278 | 309 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15347911 | 309 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15325471 | 309 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15323089 | 309 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15304389 | 310 days ago | IN | 0 S | 0.00977001 | ||||
| Claim Tokens | 15285311 | 310 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15283242 | 310 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15280841 | 310 days ago | IN | 0 S | 0.01053821 | ||||
| Claim Tokens | 15272229 | 310 days ago | IN | 0 S | 0.00911101 | ||||
| Claim Tokens | 15271636 | 310 days ago | IN | 0 S | 0.01098456 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SolisPresaleDistributor
Compiler Version
v0.7.5+commit.eb77ed08
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./lib/IERC20.sol";
import "./lib/SafeMath.sol";
import "./lib/Ownable.sol";
import "./SolisPresale.sol";
import "./lib/ReentrancyGuard.sol";
import "./SolisLuxFarm.sol";
/**
* @title SolisPresaleDistributor
* @notice This contract handles the distribution of Solis and stSolis tokens to presale participants
* @dev This contract reads participant data from the original SolisPresale contract
*/
contract SolisPresaleDistributor is Ownable, ReentrancyGuard {
using SafeMath for uint256;
// Original presale contract
SolisPresale public presaleContract;
// Token contracts
IERC20 public solisToken;
IERC20 public stSolisToken;
SolisLuxFarm public solisLuxFarmContract;
// Mapping to track if an address has claimed their tokens
mapping(address => bool) public hasClaimed;
// Distribution state
bool public distributionEnabled;
// Track total deposited tokens
uint256 public totalSolisDeposited;
uint256 public totalStSolisDeposited;
// Reentrancy guard
bool private _locked;
// Events
event DistributionStateChanged(bool enabled);
event TokensClaimed(address indexed participant, uint256 solisAmount, uint256 stSolisAmount);
event TokensDeposited(address token, uint256 amount);
/**
* @dev Constructor
* @param _presaleContract Address of the original presale contract
* @param _solisToken Address of the Solis token
* @param _stSolisToken Address of the stSolis token
* @param _luxFarmContract Address of the LuxFarm contract
*/
constructor(
address _presaleContract,
address _solisToken,
address _stSolisToken,
address _luxFarmContract
) {
require(_presaleContract != address(0), "Invalid presale contract address");
require(_solisToken != address(0), "Invalid Solis token address");
require(_stSolisToken != address(0), "Invalid stSolis token address");
require(_luxFarmContract != address(0), "Invalid luxFarm contract address");
presaleContract = SolisPresale(_presaleContract);
solisToken = IERC20(_solisToken);
stSolisToken = IERC20(_stSolisToken);
solisLuxFarmContract = SolisLuxFarm(_luxFarmContract);
}
/**
* @dev Enable or disable the distribution
* @param _enabled New state for distribution
*/
function setDistributionEnabled(bool _enabled) external onlyOwner {
distributionEnabled = _enabled;
emit DistributionStateChanged(_enabled);
}
/**
* @dev Deposit tokens for distribution
* @param _token Address of the token to deposit
* @param _amount Amount of tokens to deposit
*/
function depositTokens(address _token, uint256 _amount) external onlyOwner {
require(_token == address(solisToken) || _token == address(stSolisToken), "Invalid token");
require(_amount > 0, "Amount must be greater than 0");
// Transfer tokens from owner to this contract
require(
IERC20(_token).transferFrom(msg.sender, address(this), _amount),
"Token transfer failed"
);
// Update total deposited amounts
if (_token == address(solisToken)) {
totalSolisDeposited = totalSolisDeposited.add(_amount);
} else {
totalStSolisDeposited = totalStSolisDeposited.add(_amount);
}
emit TokensDeposited(_token, _amount);
}
/**
* @dev Calculate claimable amount for Solis and stSolis separately for a participant
* @param _participant Address of the participant
* @return solisAmount Amount of Solis tokens claimable
* @return stSolisAmount Amount of stSolis tokens claimable
*/
function calculateClaimableAmounts(address _participant) public view returns (uint256 solisAmount, uint256 stSolisAmount) {
// Get the contribution amount from the presale contract
uint256 contribution = presaleContract.contributions(_participant);
if (contribution == 0) {
return (0, 0);
}
// Get the total presale amount from the presale contract
uint256 totalPresaleAmount = presaleContract.totalPresaleAmount();
if (totalPresaleAmount == 0) {
return (0, 0);
}
// Calculate Solis and stSolis amounts independently based on deposited amounts
solisAmount = contribution.mul(totalSolisDeposited).div(totalPresaleAmount);
stSolisAmount = contribution.mul(totalStSolisDeposited).div(totalPresaleAmount);
return (solisAmount, stSolisAmount);
}
/**
* @dev Claim Solis and stSolis tokens based on contribution in the presale
*/
function claimTokens() external nonReentrant {
require(distributionEnabled, "Distribution is not enabled");
require(!hasClaimed[msg.sender], "Already claimed");
// Check if the sender is a participant in the presale
uint256 contribution = presaleContract.contributions(msg.sender);
require(contribution > 0, "Not a presale participant");
// Calculate claimable amounts independently
(uint256 solisAmount, uint256 stSolisAmount) = calculateClaimableAmounts(msg.sender);
require(solisAmount > 0 || stSolisAmount > 0, "Nothing to claim");
// Check if there are enough tokens in the contract to fulfill the claim
require(solisToken.balanceOf(address(this)) >= solisAmount, "Insufficient Solis balance");
require(stSolisToken.balanceOf(address(this)) >= stSolisAmount, "Insufficient stSolis balance");
// Mark as claimed
hasClaimed[msg.sender] = true;
// Transfer tokens to participant
if (solisAmount > 0) {
require(
solisToken.transfer(msg.sender, solisAmount),
"Solis transfer failed"
);
}
if (stSolisAmount > 0) {
require(
stSolisToken.transfer(msg.sender, stSolisAmount),
"stSolis transfer failed"
);
solisLuxFarmContract.setInitialClaimTime(msg.sender);
}
emit TokensClaimed(msg.sender, solisAmount, stSolisAmount);
}
/**
* @dev Check if a participant can claim tokens
* @param _participant Address of the participant
* @return bool True if the participant can claim tokens
*/
function canClaim(address _participant) external view returns (bool) {
if (hasClaimed[_participant]) {
return false;
}
uint256 contribution = presaleContract.contributions(_participant);
return contribution > 0;
}
/**
* @dev Emergency withdraw function for owner to recover tokens
* @param _token Address of the token to withdraw
*/
function emergencyWithdraw(address _token) external onlyOwner {
IERC20 token = IERC20(_token);
uint256 balance = token.balanceOf(address(this));
require(balance > 0, "No tokens to withdraw");
require(token.transfer(owner(), balance), "Transfer failed");
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies in extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard}
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(
address(this).balance >= amount,
"Address: insufficient balance"
);
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(bool success, ) = recipient.call{value: amount}("");
require(
success,
"Address: unable to send value, recipient may have reverted"
);
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain`call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data
) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return _functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return
functionCallWithValue(
target,
data,
value,
"Address: low-level call with value failed"
);
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(
address(this).balance >= value,
"Address: insufficient balance for call"
);
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{value: value}(
data
);
return _verifyCallResult(success, returndata, errorMessage);
}
function _functionCallWithValue(
address target,
bytes memory data,
uint256 weiValue,
string memory errorMessage
) private returns (bytes memory) {
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{value: weiValue}(
data
);
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data
) internal view returns (bytes memory) {
return
functionStaticCall(
target,
data,
"Address: low-level static call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.3._
*/
function functionDelegateCall(
address target,
bytes memory data
) internal returns (bytes memory) {
return
functionDelegateCall(
target,
data,
"Address: low-level delegate call failed"
);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.3._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
function addressToString(
address _address
) internal pure returns (string memory) {
bytes32 _bytes = bytes32(uint256(_address));
bytes memory HEX = "0123456789abcdef";
bytes memory _addr = new bytes(42);
_addr[0] = "0";
_addr[1] = "x";
for (uint256 i = 0; i < 20; i++) {
_addr[2 + i * 2] = HEX[uint8(_bytes[i + 12] >> 4)];
_addr[3 + i * 2] = HEX[uint8(_bytes[i + 12] & 0x0f)];
}
return string(_addr);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./SafeMath.sol";
library Counters {
using SafeMath for uint256;
struct Counter {
uint256 _value; // default: 0
}
function current(Counter storage counter) internal view returns (uint256) {
return counter._value;
}
function increment(Counter storage counter) internal {
counter._value += 1;
}
function decrement(Counter storage counter) internal {
counter._value = counter._value.sub(1);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(
Set storage set,
bytes32 value
) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(
Set storage set,
uint256 index
) private view returns (bytes32) {
require(
set._values.length > index,
"EnumerableSet: index out of bounds"
);
return set._values[index];
}
function _getValues(
Set storage set_
) private view returns (bytes32[] storage) {
return set_._values;
}
// TODO needs insert function that maintains order.
// TODO needs NatSpec documentation comment.
/**
* Inserts new value by moving existing value at provided index to end
* of array and setting provided value at provided index
*/
function _insert(
Set storage set_,
uint256 index_,
bytes32 valueToInsert_
) private returns (bool) {
require(set_._values.length > index_);
require(
!_contains(set_, valueToInsert_),
"Remove value you wish to insert if you wish to reorder array."
);
bytes32 existingValue_ = _at(set_, index_);
set_._values[index_] = valueToInsert_;
return _add(set_, existingValue_);
}
struct Bytes4Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes4Set storage set, bytes4 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(
Bytes4Set storage set,
bytes4 value
) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(
Bytes4Set storage set,
bytes4 value
) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(Bytes4Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(
Bytes4Set storage set,
uint256 index
) internal view returns (bytes4) {
return bytes4(_at(set._inner, index));
}
function getValues(
Bytes4Set storage set_
) internal view returns (bytes4[] memory) {
bytes4[] memory bytes4Array_;
for (
uint256 iteration_ = 0;
_length(set_._inner) > iteration_;
iteration_++
) {
bytes4Array_[iteration_] = bytes4(_at(set_._inner, iteration_));
}
return bytes4Array_;
}
function insert(
Bytes4Set storage set_,
uint256 index_,
bytes4 valueToInsert_
) internal returns (bool) {
return _insert(set_._inner, index_, valueToInsert_);
}
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(
Bytes32Set storage set,
bytes32 value
) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(
Bytes32Set storage set,
bytes32 value
) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(
Bytes32Set storage set,
bytes32 value
) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(
Bytes32Set storage set,
uint256 index
) internal view returns (bytes32) {
return _at(set._inner, index);
}
function getValues(
Bytes32Set storage set_
) internal view returns (bytes4[] memory) {
bytes4[] memory bytes4Array_;
for (
uint256 iteration_ = 0;
_length(set_._inner) >= iteration_;
iteration_++
) {
bytes4Array_[iteration_] = bytes4(at(set_, iteration_));
}
return bytes4Array_;
}
function insert(
Bytes32Set storage set_,
uint256 index_,
bytes32 valueToInsert_
) internal returns (bool) {
return _insert(set_._inner, index_, valueToInsert_);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(
AddressSet storage set,
address value
) internal returns (bool) {
return _add(set._inner, bytes32(uint256(value)));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(
AddressSet storage set,
address value
) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(value)));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(
AddressSet storage set,
address value
) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(value)));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(
AddressSet storage set,
uint256 index
) internal view returns (address) {
return address(uint256(_at(set._inner, index)));
}
/**
* TODO Might require explicit conversion of bytes32[] to address[].
* Might require iteration.
*/
function getValues(
AddressSet storage set_
) internal view returns (address[] memory) {
address[] memory addressArray;
for (
uint256 iteration_ = 0;
_length(set_._inner) >= iteration_;
iteration_++
) {
addressArray[iteration_] = at(set_, iteration_);
}
return addressArray;
}
function insert(
AddressSet storage set_,
uint256 index_,
address valueToInsert_
) internal returns (bool) {
return _insert(set_._inner, index_, bytes32(uint256(valueToInsert_)));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(
UintSet storage set,
uint256 value
) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(
UintSet storage set,
uint256 value
) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(
UintSet storage set,
uint256 index
) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
struct UInt256Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(
UInt256Set storage set,
uint256 value
) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(
UInt256Set storage set,
uint256 value
) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(
UInt256Set storage set,
uint256 value
) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UInt256Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(
UInt256Set storage set,
uint256 index
) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./IERC20.sol";
import "./SafeMath.sol";
abstract contract ERC20 is IERC20 {
using SafeMath for uint256;
// TODO comment actual hash value.
bytes32 private constant ERC20TOKEN_ERC1820_INTERFACE_ID =
keccak256("ERC20Token");
// Present in ERC777
mapping(address => uint256) internal _balances;
// Present in ERC777
mapping(address => mapping(address => uint256)) internal _allowances;
// Present in ERC777
uint256 internal _totalSupply;
// Present in ERC777
string internal _name;
// Present in ERC777
string internal _symbol;
// Present in ERC777
uint8 internal _decimals;
constructor(string memory name_, string memory symbol_, uint8 decimals_) {
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view override returns (uint8) {
return _decimals;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function balanceOf(
address account
) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(msg.sender, recipient, 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) {
_approve(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(
sender,
msg.sender,
_allowances[sender][msg.sender].sub(
amount,
"ERC20: transfer amount exceeds allowance"
)
);
return true;
}
function increaseAllowance(
address spender,
uint256 addedValue
) public virtual returns (bool) {
_approve(
msg.sender,
spender,
_allowances[msg.sender][spender].add(addedValue)
);
return true;
}
function decreaseAllowance(
address spender,
uint256 subtractedValue
) public virtual returns (bool) {
_approve(
msg.sender,
spender,
_allowances[msg.sender][spender].sub(
subtractedValue,
"ERC20: decreased allowance below zero"
)
);
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(
amount,
"ERC20: transfer amount exceeds balance"
);
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(sender, recipient, amount);
}
function _mint(address account_, uint256 amount_) internal virtual {
require(account_ != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(this), account_, amount_);
_totalSupply = _totalSupply.add(amount_);
_balances[account_] = _balances[account_].add(amount_);
emit Transfer(address(this), 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);
_balances[account] = _balances[account].sub(
amount,
"ERC20: burn amount exceeds balance"
);
_totalSupply = _totalSupply.sub(amount);
emit Transfer(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 _beforeTokenTransfer(
address from_,
address to_,
uint256 amount_
) internal virtual {}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./IERC20.sol";
import "./IERC2612Permit.sol";
import "./Counters.sol";
import "./ERC20.sol";
abstract contract ERC20Permit is ERC20, IERC2612Permit {
using Counters for Counters.Counter;
mapping(address => Counters.Counter) private _nonces;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH =
0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
bytes32 public DOMAIN_SEPARATOR;
constructor() {
uint256 chainID;
assembly {
chainID := chainid()
}
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name())),
keccak256(bytes("1")), // Version
chainID,
address(this)
)
);
}
/**
* @dev See {IERC2612Permit-permit}.
*
*/
function permit(
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual override {
require(block.timestamp <= deadline, "Permit: expired deadline");
bytes32 hashStruct = keccak256(
abi.encode(
PERMIT_TYPEHASH,
owner,
spender,
amount,
_nonces[owner].current(),
deadline
)
);
bytes32 _hash = keccak256(
abi.encodePacked(uint16(0x1901), DOMAIN_SEPARATOR, hashStruct)
);
address signer = ecrecover(_hash, v, r, s);
require(
signer != address(0) && signer == owner,
"ZeroSwapPermit: Invalid signature"
);
_nonces[owner].increment();
_approve(owner, spender, amount);
}
/**
* @dev See {IERC2612Permit-nonces}.
*/
function nonces(address owner) public view override returns (uint256) {
return _nonces[owner].current();
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
interface IERC20 {
function decimals() external view returns (uint8);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(
address owner,
address spender
) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
interface IERC20Mintable {
function mint(address account, uint256 amount) external;
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
interface IERC2612Permit {
function permit(
address owner,
address spender,
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
interface IOwnable {
function owner() external view returns (address);
function renounceOwnership() external;
function transferOwnership(address newOwner_) external;
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
interface IOwnableManagement {
function manager() external view returns (address);
function renounceManagement() external;
function pushManagement(address newOwner_) external;
function pullManagement() external;
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
interface IStSolis {
function rebase(uint256 profit_, uint256 epoch_) external returns (uint256);
function circulatingSupply() external view returns (uint);
function balanceOf(address who) external view returns (uint);
function gonsForBalance( uint amount ) external view returns ( uint );
function balanceForGons( uint gons ) external view returns ( uint );
function index() external view returns (uint);
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./IOwnable.sol";
contract Ownable is IOwnable {
address internal _owner;
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
constructor() {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view override returns (address) {
return _owner;
}
modifier onlyOwner() {
require(_owner == msg.sender, "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual override onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(
address newOwner_
) public virtual override onlyOwner {
require(
newOwner_ != address(0),
"Ownable: new owner is the zero address"
);
emit OwnershipTransferred(_owner, newOwner_);
_owner = newOwner_;
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./IOwnableManagement.sol";
contract OwnableManagement is IOwnableManagement {
address internal _owner;
address internal _newOwner;
event OwnershipPushed(address indexed previousOwner, address indexed newOwner);
event OwnershipPulled(address indexed previousOwner, address indexed newOwner);
constructor () {
_owner = msg.sender;
emit OwnershipPushed( address(0), _owner );
}
function manager() public view override returns (address) {
return _owner;
}
modifier onlyManager() {
require( _owner == msg.sender, "Ownable: caller is not the owner" );
_;
}
function renounceManagement() public virtual override onlyManager() {
emit OwnershipPushed( _owner, address(0) );
_owner = address(0);
}
function pushManagement( address newOwner_ ) public virtual override onlyManager() {
require( newOwner_ != address(0), "Ownable: new owner is the zero address");
emit OwnershipPushed( _owner, newOwner_ );
_newOwner = newOwner_;
}
function pullManagement() public virtual override {
require( msg.sender == _newOwner, "Ownable: must be new owner to pull");
emit OwnershipPulled( _owner, _newOwner );
_owner = _newOwner;
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
/**
* @title ReentrancyGuard
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*/
contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./SafeMath.sol";
import "./Address.sol";
import "./IERC20.sol";
library SafeERC20 {
using SafeMath for uint256;
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 {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
// solhint-disable-next-line max-line-length
require((value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).add(value);
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves.
// A Solidity high level call has three parts:
// 1. The target address is checked to verify it contains contract code
// 2. The call itself is made, and success asserted
// 3. The return value is decoded, which in turn checks the size of the returned data.
// solhint-disable-next-line max-line-length
require(address(token).isContract(), "SafeERC20: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "SafeERC20: low-level call failed");
if (returndata.length > 0) { // Return data is optional
// solhint-disable-next-line max-line-length
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
library SafeMath {
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function add32(uint32 a, uint32 b) internal pure returns (uint32) {
uint32 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return sub(a, b, "SafeMath: subtraction overflow");
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b <= a, errorMessage);
uint256 c = a - b;
return c;
}
function sub32(uint32 a, uint32 b) internal pure returns (uint32) {
return sub32(a, b, "SafeMath: subtraction overflow");
}
function sub32(
uint32 a,
uint32 b,
string memory errorMessage
) internal pure returns (uint32) {
require(b <= a, errorMessage);
uint32 c = a - b;
return c;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function mul32(uint32 a, uint32 b) internal pure returns (uint32) {
if (a == 0) {
return 0;
}
uint32 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return div(a, b, "SafeMath: division by zero");
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b > 0, errorMessage);
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return mod(a, b, "SafeMath: modulo by zero");
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
require(b != 0, errorMessage);
return a % b;
}
function sqrrt(uint256 a) internal pure returns (uint c) {
if (a > 3) {
c = a;
uint b = add(div(a, 2), 1);
while (b < c) {
c = b;
b = div(add(div(a, b), b), 2);
}
} else if (a != 0) {
c = 1;
}
}
function percentageAmount(
uint256 total_,
uint8 percentage_
) internal pure returns (uint256 percentAmount_) {
return div(mul(total_, percentage_), 1000);
}
function substractPercentage(
uint256 total_,
uint8 percentageToSub_
) internal pure returns (uint256 result_) {
return sub(total_, div(mul(total_, percentageToSub_), 1000));
}
function percentageOfTotal(
uint256 part_,
uint256 total_
) internal pure returns (uint256 percent_) {
return div(mul(part_, 100), total_);
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow, so we distribute
return (a / 2) + (b / 2) + (((a % 2) + (b % 2)) / 2);
}
function quadraticPricing(
uint256 payment_,
uint256 multiplier_
) internal pure returns (uint256) {
return sqrrt(mul(multiplier_, payment_));
}
function bondingCurve(
uint256 supply_,
uint256 multiplier_
) internal pure returns (uint256) {
return mul(multiplier_, supply_);
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./Ownable.sol";
contract VaultOwned is Ownable {
address internal _vault;
function setVault(address vault_) external onlyOwner returns (bool) {
_vault = vault_;
return true;
}
function vault() public view returns (address) {
return _vault;
}
modifier onlyVault() {
require(_vault == msg.sender, "VaultOwned: caller is not the Vault");
_;
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.7.5;
import "./lib/SafeMath.sol";
import "./lib/Address.sol";
import "./lib/SafeERC20.sol";
import "./lib/OwnableManagement.sol";
import "./lib/IERC20.sol";
import "./lib/IStSolis.sol";
import "./lib/IERC20Mintable.sol";
import "./lib/ReentrancyGuard.sol";
/**
* @title SolisLuxFarm
* @notice Contract for farming LUX rewards from stSolis
* @dev Users can hold stSolis to earn LUX rewards
*/
contract SolisLuxFarm is OwnableManagement, ReentrancyGuard {
using SafeMath for uint256;
using SafeERC20 for IERC20;
// Tokens
address public immutable lux;
address public immutable stSolis;
address public immutable stakingHelper;
address public presaleDistributor;
// User data
mapping(address => uint) public lastStSolisClaimTime; // Last time user claimed stSolis rewards
// Configurable rewards (set by manager)
uint public dailyStSolisHolderReward = 200000 * 10**9; // boosted to 200k LUX for stSolis holders for launch
// Constants
uint public constant BASIS_POINTS = 10000; // Added constant for basis points
uint public constant ONE_DAY = 1 days; // One day in seconds
// Events
event ClaimLux(address indexed user, uint amount);
event ClaimStSolisLux(address indexed user, uint amount);
event DailyRewardChanged(uint newAmount);
/**
* @notice Constructor
* @param _lux LUX token address
* @param _stSolis stSolis token address
* @param _stakingHelper StakingHelper contract address
*/
constructor(
address _lux,
address _stSolis,
address _stakingHelper
) {
require(_lux != address(0), "Invalid LUX address");
require(_stSolis != address(0), "Invalid stSolis address");
require(_stakingHelper != address(0), "Invalid stakingHelper address");
lux = _lux;
stSolis = _stSolis;
stakingHelper = _stakingHelper;
}
function setPresaleDistributor(address _presaleDistributor) external onlyManager {
require(_presaleDistributor != address(0), "Invalid presaleDistributor address");
presaleDistributor = _presaleDistributor;
}
/**
* @notice Set the daily reward amount for stSolis holders
* @param _amount New daily reward amount
*/
function setDailyReward(uint _amount) external onlyManager {
require(_amount > 0, "Reward must be greater than 0");
dailyStSolisHolderReward = _amount;
emit DailyRewardChanged(_amount);
}
/**
* @notice Calculate rewards from stSolis holdings for a user based on time since last stSolis claim
* @param _user Address of the user
* @return uint stSolis rewards
*/
function calculateStSolisRewards(address _user) public view returns (uint) {
uint claimTime = lastStSolisClaimTime[_user];
if (claimTime == 0) {
return 0;
}
uint stSolisBalance = IERC20(stSolis).balanceOf(_user);
if (stSolisBalance == 0) return 0;
uint totalStSolis = IStSolis(stSolis).circulatingSupply();
if (totalStSolis == 0) return 0;
uint timeElapsed = block.timestamp.sub(claimTime);
uint timeRatio = timeElapsed.mul(BASIS_POINTS).div(ONE_DAY);
return stSolisBalance.mul(dailyStSolisHolderReward).mul(timeRatio)
.div(totalStSolis).div(BASIS_POINTS);
}
/**
* @notice Claim and withdraw LUX rewards from stSolis holdings
* @dev Calculates stSolis rewards based on time since last stSolis claim, mints them to user
* @return uint Amount of LUX claimed
*/
function claimLux() external nonReentrant returns (uint) {
require(IERC20(stSolis).balanceOf(msg.sender) > 0, "Must have stSolis balance");
uint reward = calculateStSolisRewards(msg.sender);
require(reward > 0, "No rewards to claim");
// Update last stSolis claim time
lastStSolisClaimTime[msg.sender] = block.timestamp;
IERC20Mintable(lux).mint(msg.sender, reward);
emit ClaimLux(msg.sender, reward);
emit ClaimStSolisLux(msg.sender, reward);
return reward;
}
/**
* @notice Get the last time a user claimed stSolis rewards
* @param _user Address of the user
* @return uint Timestamp of last stSolis claim
*/
function getLastClaimTime(address _user) external view returns (uint) {
return lastStSolisClaimTime[_user];
}
/**
* @notice Emergency function to recover tokens accidentally sent to the contract
* @param _token Address of the token to recover
* @param _amount Amount of tokens to recover
*/
function recoverERC20(address _token, uint256 _amount) external onlyManager {
IERC20(_token).safeTransfer(manager(), _amount);
}
/**
* @notice Set initial stSolis claim time for a user
* @dev Can only be called by the StakingHelper contract
* @param _user Address of the user to set initial claim time for
*/
function setInitialClaimTime(address _user) external {
require(msg.sender == stakingHelper || msg.sender == presaleDistributor, "Only StakingHelper or PresaleDistributor can call");
require(_user != address(0), "Invalid user address");
lastStSolisClaimTime[_user] = block.timestamp;
}
}// SPDX-License-Identifier: AGPL-3.0-or-later
pragma abicoder v2;
pragma solidity 0.7.5;
import "./lib/EnumerableSet.sol";
import "./lib/IERC2612Permit.sol";
import "./lib/IERC20.sol";
import "./lib/ERC20Permit.sol";
import "./lib/VaultOwned.sol";
import "./lib/SafeMath.sol";
import "./lib/Ownable.sol";
contract SolisPresale is Ownable {
using SafeMath for uint256;
using EnumerableSet for EnumerableSet.AddressSet;
// Presale token
IERC20 public presaleToken;
// Solis token
IERC20 public solisToken;
// Whitelist of addresses allowed to participate in presale
EnumerableSet.AddressSet private _whitelist;
// Set of participants who have contributed to the presale
EnumerableSet.AddressSet private _participants;
// Mapping to track contributions per address
mapping(address => uint256) public contributions;
// Mapping to track if an address has claimed their tokens
mapping(address => bool) public hasClaimed;
// Total amount of presale tokens received
uint256 public totalPresaleAmount;
// Total amount of Solis tokens to distribute
uint256 public totalSolisAmount;
// Presale state variables
bool public presaleEnabled;
bool public distributionEnabled;
bool public refundsEnabled;
// Reentrancy guard
bool private _locked;
modifier nonReentrant() {
require(!_locked, "ReentrancyGuard: reentrant call");
_locked = true;
_;
_locked = false;
}
// Minimum and maximum contribution limits per address
uint256 public minContribution = 500 * 10**18;
uint256 public maxContribution = 15000 * 10**18;
// Hard cap for the presale
uint256 public hardCap = 750000 * 10**18;
// Events
event WhitelistAdded(address indexed account);
event WhitelistRemoved(address indexed account);
event PresaleStateChanged(bool enabled);
event DistributionStateChanged(bool enabled);
event RefundsStateChanged(bool enabled);
event PresaleContribution(address indexed participant, uint256 amount);
event SolisDeposited(uint256 amount);
event TokensClaimed(address indexed participant, uint256 amount);
event Refunded(address indexed participant, uint256 amount);
constructor(address _presaleToken) {
presaleToken = IERC20(_presaleToken);
}
/**
* @dev Add an address to the whitelist
* @param _account Address to add to the whitelist
*/
function addToWhitelist(address _account) external onlyOwner {
require(_account != address(0), "Cannot add zero address");
require(_whitelist.add(_account), "Address already whitelisted");
emit WhitelistAdded(_account);
}
/**
* @dev Add multiple addresses to the whitelist
* @param _accounts Array of addresses to add to the whitelist
*/
function addMultipleToWhitelist(address[] calldata _accounts) external onlyOwner {
for (uint256 i = 0; i < _accounts.length; i++) {
if (_accounts[i] != address(0) && _whitelist.add(_accounts[i])) {
emit WhitelistAdded(_accounts[i]);
}
}
}
/**
* @dev Remove an address from the whitelist
* @param _account Address to remove from the whitelist
*/
function removeFromWhitelist(address _account) external onlyOwner {
require(_whitelist.remove(_account), "Address not whitelisted");
emit WhitelistRemoved(_account);
}
/**
* @dev Check if an address is whitelisted
* @param _account Address to check
* @return bool True if address is whitelisted
*/
function isWhitelisted(address _account) external view returns (bool) {
return _whitelist.contains(_account);
}
/**
* @dev Enable or disable the presale
* @param _enabled New state for presale
*/
function setPresaleEnabled(bool _enabled) external onlyOwner {
presaleEnabled = _enabled;
emit PresaleStateChanged(_enabled);
}
/**
* @dev Enable or disable the distribution
* @param _enabled New state for distribution
*/
function setDistributionEnabled(bool _enabled) external onlyOwner {
distributionEnabled = _enabled;
emit DistributionStateChanged(_enabled);
}
/**
* @dev Enable or disable refunds
*/
function setRefundsEnabled(bool _enabled) external onlyOwner {
refundsEnabled = _enabled;
emit RefundsStateChanged(_enabled);
}
/**
* @dev Participate in the presale by sending presale tokens
* @param _amount Amount of presale tokens to contribute
*/
function participate(uint256 _amount) external nonReentrant {
require(presaleEnabled, "Presale is not enabled");
require(_whitelist.contains(msg.sender), "Address not whitelisted");
require(_amount > 0, "Amount must be greater than 0");
require(_amount >= minContribution, "Below minimum contribution");
require(contributions[msg.sender].add(_amount) <= maxContribution, "Exceeds maximum contribution");
require(totalPresaleAmount.add(_amount) <= hardCap, "Hard cap reached");
// Transfer presale tokens from participant to this contract
require(
presaleToken.transferFrom(msg.sender, address(this), _amount),
"Token transfer failed"
);
// Add participant to the participants set if not already added
if (!_participants.contains(msg.sender)) {
_participants.add(msg.sender);
}
// Update contribution amount
contributions[msg.sender] = contributions[msg.sender].add(_amount);
// Update total presale amount
totalPresaleAmount = totalPresaleAmount.add(_amount);
emit PresaleContribution(msg.sender, _amount);
}
/**
* @dev Set the Solis token address and deposit Solis tokens for distribution
* @param _solisToken Address of the Solis token
* @param _amount Amount of Solis tokens to deposit
*/
function depositSolisTokens(address _solisToken, uint256 _amount) external onlyOwner {
require(_solisToken != address(0), "Invalid Solis token address");
require(_amount > 0, "Amount must be greater than 0");
require(!presaleEnabled, "Presale must be disabled");
// Set Solis token address if not already set
if (address(solisToken) == address(0)) {
solisToken = IERC20(_solisToken);
} else {
require(address(solisToken) == _solisToken, "Solis token address mismatch");
}
// Transfer Solis tokens from owner to this contract
require(
solisToken.transferFrom(msg.sender, address(this), _amount),
"Token transfer failed"
);
// Update total Solis amount
totalSolisAmount = totalSolisAmount.add(_amount);
emit SolisDeposited(_amount);
}
/**
* @dev Claim Solis tokens based on contribution
*/
function claimTokens() external nonReentrant {
require(distributionEnabled, "Distribution is not enabled");
require(_participants.contains(msg.sender), "Not a participant");
require(!hasClaimed[msg.sender], "Already claimed");
require(totalPresaleAmount > 0, "No presale contributions");
require(totalSolisAmount > 0, "No Solis tokens to distribute");
// Calculate claimable amount
uint256 claimableAmount = calculateClaimableAmount(msg.sender);
require(claimableAmount > 0, "Nothing to claim");
// Mark as claimed
hasClaimed[msg.sender] = true;
// Transfer Solis tokens to participant
require(
solisToken.transfer(msg.sender, claimableAmount),
"Token transfer failed"
);
emit TokensClaimed(msg.sender, claimableAmount);
}
/**
* @dev Calculate claimable Solis tokens for a participant
* @param _participant Address of the participant
* @return uint256 Amount of Solis tokens claimable
*/
function calculateClaimableAmount(address _participant) public view returns (uint256) {
if (totalPresaleAmount == 0 || totalSolisAmount == 0) {
return 0;
}
// Calculate based on the formula: contribution * totalSolisTokens / totalPresale
return contributions[_participant].mul(totalSolisAmount).div(totalPresaleAmount);
}
/**
* @dev Get the number of whitelisted addresses
* @return uint256 Number of whitelisted addresses
*/
function getWhitelistCount() external view returns (uint256) {
return _whitelist.length();
}
/**
* @dev Get the number of participants
* @return uint256 Number of participants
*/
function getParticipantCount() external view returns (uint256) {
return _participants.length();
}
/**
* @dev Get participant at index
* @param _index Index of the participant
* @return address Participant address
*/
function getParticipantAtIndex(uint256 _index) external view returns (address) {
require(_index < _participants.length(), "Index out of bounds");
return _participants.at(_index);
}
/**
* @dev Emergency withdraw function for owner to recover tokens
* @param _token Address of the token to withdraw
*/
function emergencyWithdraw(address _token) external onlyOwner {
IERC20 token = IERC20(_token);
uint256 balance = token.balanceOf(address(this));
require(balance > 0, "No tokens to withdraw");
require(token.transfer(owner(), balance), "Transfer failed");
}
/**
* @dev Refund function for participants
*/
function refund() external nonReentrant {
require(refundsEnabled, "Refunds not enabled");
require(_participants.contains(msg.sender), "Not a participant");
require(contributions[msg.sender] > 0, "No contribution to refund");
uint256 amount = contributions[msg.sender];
contributions[msg.sender] = 0;
_participants.remove(msg.sender);
// Update total presale amount
totalPresaleAmount = totalPresaleAmount.sub(amount);
// Transfer tokens back to participant
require(
presaleToken.transfer(msg.sender, amount),
"Refund transfer failed"
);
emit Refunded(msg.sender, amount);
}
function setContributionLimits(uint256 _min, uint256 _max) external onlyOwner {
require(_min <= _max, "Min must be <= max");
minContribution = _min;
maxContribution = _max;
}
function setHardCap(uint256 _hardCap) external onlyOwner {
hardCap = _hardCap;
}
}{
"optimizer": {
"enabled": true,
"runs": 1000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_presaleContract","type":"address"},{"internalType":"address","name":"_solisToken","type":"address"},{"internalType":"address","name":"_stSolisToken","type":"address"},{"internalType":"address","name":"_luxFarmContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"enabled","type":"bool"}],"name":"DistributionStateChanged","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":"participant","type":"address"},{"indexed":false,"internalType":"uint256","name":"solisAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stSolisAmount","type":"uint256"}],"name":"TokensClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensDeposited","type":"event"},{"inputs":[{"internalType":"address","name":"_participant","type":"address"}],"name":"calculateClaimableAmounts","outputs":[{"internalType":"uint256","name":"solisAmount","type":"uint256"},{"internalType":"uint256","name":"stSolisAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_participant","type":"address"}],"name":"canClaim","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributionEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"hasClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"presaleContract","outputs":[{"internalType":"contract SolisPresale","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_enabled","type":"bool"}],"name":"setDistributionEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"solisLuxFarmContract","outputs":[{"internalType":"contract SolisLuxFarm","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"solisToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stSolisToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSolisDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStSolisDeposited","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner_","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b5060405161176b38038061176b8339818101604052608081101561003357600080fd5b5080516020820151604080840151606090940151600080546001600160a01b031916331780825592519495939491926001600160a01b0316917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3600180556001600160a01b0384166100f0576040805162461bcd60e51b815260206004820181905260248201527f496e76616c69642070726573616c6520636f6e74726163742061646472657373604482015290519081900360640190fd5b6001600160a01b03831661014b576040805162461bcd60e51b815260206004820152601b60248201527f496e76616c696420536f6c697320746f6b656e20616464726573730000000000604482015290519081900360640190fd5b6001600160a01b0382166101a6576040805162461bcd60e51b815260206004820152601d60248201527f496e76616c6964207374536f6c697320746f6b656e2061646472657373000000604482015290519081900360640190fd5b6001600160a01b038116610201576040805162461bcd60e51b815260206004820181905260248201527f496e76616c6964206c75784661726d20636f6e74726163742061646472657373604482015290519081900360640190fd5b600280546001600160a01b039586166001600160a01b031991821617909155600380549486169482169490941790935560048054928516928416929092179091556005805491909316911617905561150d8061025e6000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c806373b2e80e116100b2578063bf3506c111610081578063e004a3d811610066578063e004a3d8146102a0578063e6c20dd1146102a8578063f2fde38b146102b05761011b565b8063bf3506c11461023b578063dbac3d3d146102615761011b565b806373b2e80e146101d757806386608326146102115780638acca092146102195780638da5cb5b146102335761011b565b806363d9df85116100ee57806363d9df851461017557806366168bd71461017d5780636ff1c9bc146101a9578063715018a6146101cf5761011b565b806307a15cd41461012057806333a2ef861461014457806343bb18ff1461014c57806348c54b9d1461016d575b600080fd5b6101286102d6565b604080516001600160a01b039092168252519081900360200190f35b6101286102e5565b61016b6004803603602081101561016257600080fd5b503515156102f4565b005b61016b61039a565b610128610a0e565b61016b6004803603604081101561019357600080fd5b506001600160a01b038135169060200135610a1d565b61016b600480360360208110156101bf57600080fd5b50356001600160a01b0316610cba565b61016b610ec4565b6101fd600480360360208110156101ed57600080fd5b50356001600160a01b0316610f7a565b604080519115158252519081900360200190f35b6101fd610f8f565b610221610f98565b60408051918252519081900360200190f35b610128610f9e565b6101fd6004803603602081101561025157600080fd5b50356001600160a01b0316610fad565b6102876004803603602081101561027757600080fd5b50356001600160a01b031661105e565b6040805192835260208301919091528051918290030190f35b6101286111d4565b6102216111e3565b61016b600480360360208110156102c657600080fd5b50356001600160a01b03166111e9565b6004546001600160a01b031681565b6003546001600160a01b031681565b6000546001600160a01b03163314610353576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007805482151560ff19909116811790915560408051918252517f11d48e11836d1d72286877c5b0f66b9a7c76273a1a1037b299c8460a497938679181900360200190a150565b600260015414156103f2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260015560075460ff1661044e576040805162461bcd60e51b815260206004820152601b60248201527f446973747269627574696f6e206973206e6f7420656e61626c65640000000000604482015290519081900360640190fd5b3360009081526006602052604090205460ff16156104b3576040805162461bcd60e51b815260206004820152600f60248201527f416c726561647920636c61696d65640000000000000000000000000000000000604482015290519081900360640190fd5b6002546040805163042e94c960e41b815233600482015290516000926001600160a01b0316916342e94c90916024808301926020929190829003018186803b1580156104fe57600080fd5b505afa158015610512573d6000803e3d6000fd5b505050506040513d602081101561052857600080fd5b505190508061057e576040805162461bcd60e51b815260206004820152601960248201527f4e6f7420612070726573616c65207061727469636970616e7400000000000000604482015290519081900360640190fd5b60008061058a3361105e565b91509150600082118061059d5750600081115b6105ee576040805162461bcd60e51b815260206004820152601060248201527f4e6f7468696e6720746f20636c61696d00000000000000000000000000000000604482015290519081900360640190fd5b600354604080516370a0823160e01b8152306004820152905184926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561063857600080fd5b505afa15801561064c573d6000803e3d6000fd5b505050506040513d602081101561066257600080fd5b505110156106b7576040805162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e7420536f6c69732062616c616e6365000000000000604482015290519081900360640190fd5b60048054604080516370a0823160e01b815230938101939093525183926001600160a01b03909216916370a08231916024808301926020929190829003018186803b15801561070557600080fd5b505afa158015610719573d6000803e3d6000fd5b505050506040513d602081101561072f57600080fd5b50511015610784576040805162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e74207374536f6c69732062616c616e636500000000604482015290519081900360640190fd5b336000908152600660205260409020805460ff191660011790558115610875576003546040805163a9059cbb60e01b81523360048201526024810185905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156107f857600080fd5b505af115801561080c573d6000803e3d6000fd5b505050506040513d602081101561082257600080fd5b5051610875576040805162461bcd60e51b815260206004820152601560248201527f536f6c6973207472616e73666572206661696c65640000000000000000000000604482015290519081900360640190fd5b80156109cb57600480546040805163a9059cbb60e01b8152339381019390935260248301849052516001600160a01b039091169163a9059cbb9160448083019260209291908290030181600087803b1580156108d057600080fd5b505af11580156108e4573d6000803e3d6000fd5b505050506040513d60208110156108fa57600080fd5b505161094d576040805162461bcd60e51b815260206004820152601760248201527f7374536f6c6973207472616e73666572206661696c6564000000000000000000604482015290519081900360640190fd5b600554604080517f45af59d300000000000000000000000000000000000000000000000000000000815233600482015290516001600160a01b03909216916345af59d39160248082019260009290919082900301818387803b1580156109b257600080fd5b505af11580156109c6573d6000803e3d6000fd5b505050505b6040805183815260208101839052815133927f9923b4306c6c030f2bdfbf156517d5983b87e15b96176da122cd4f2effa4ba7b928290030190a250506001805550565b6002546001600160a01b031681565b6000546001600160a01b03163314610a7c576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6003546001600160a01b0383811691161480610aa557506004546001600160a01b038381169116145b610af6576040805162461bcd60e51b815260206004820152600d60248201527f496e76616c696420746f6b656e00000000000000000000000000000000000000604482015290519081900360640190fd5b60008111610b4b576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810183905290516001600160a01b038416916323b872dd9160648083019260209291908290030181600087803b158015610bb957600080fd5b505af1158015610bcd573d6000803e3d6000fd5b505050506040513d6020811015610be357600080fd5b5051610c36576040805162461bcd60e51b815260206004820152601560248201527f546f6b656e207472616e73666572206661696c65640000000000000000000000604482015290519081900360640190fd5b6003546001600160a01b0383811691161415610c6157600854610c5990826112f5565b600855610c72565b600954610c6e90826112f5565b6009555b604080516001600160a01b03841681526020810183905281517f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e929181900390910190a15050565b6000546001600160a01b03163314610d19576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b604080516370a0823160e01b8152306004820152905182916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015610d6457600080fd5b505afa158015610d78573d6000803e3d6000fd5b505050506040513d6020811015610d8e57600080fd5b5051905080610de4576040805162461bcd60e51b815260206004820152601560248201527f4e6f20746f6b656e7320746f2077697468647261770000000000000000000000604482015290519081900360640190fd5b816001600160a01b031663a9059cbb610dfb610f9e565b836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610e4257600080fd5b505af1158015610e56573d6000803e3d6000fd5b505050506040513d6020811015610e6c57600080fd5b5051610ebf576040805162461bcd60e51b815260206004820152600f60248201527f5472616e73666572206661696c65640000000000000000000000000000000000604482015290519081900360640190fd5b505050565b6000546001600160a01b03163314610f23576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b60066020526000908152604090205460ff1681565b60075460ff1681565b60095481565b6000546001600160a01b031690565b6001600160a01b03811660009081526006602052604081205460ff1615610fd657506000611059565b6002546040805163042e94c960e41b81526001600160a01b038581166004830152915160009392909216916342e94c9091602480820192602092909190829003018186803b15801561102757600080fd5b505afa15801561103b573d6000803e3d6000fd5b505050506040513d602081101561105157600080fd5b505115159150505b919050565b6002546040805163042e94c960e41b81526001600160a01b0384811660048301529151600093849384939116916342e94c9091602480820192602092909190829003018186803b1580156110b157600080fd5b505afa1580156110c5573d6000803e3d6000fd5b505050506040513d60208110156110db57600080fd5b50519050806110f15760008092509250506111cf565b600254604080517f98de542100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b0316916398de5421916004808301926020929190829003018186803b15801561114f57600080fd5b505afa158015611163573d6000803e3d6000fd5b505050506040513d602081101561117957600080fd5b5051905080611190576000809350935050506111cf565b6111af816111a96008548561135890919063ffffffff16565b906113b1565b93506111ca816111a96009548561135890919063ffffffff16565b925050505b915091565b6005546001600160a01b031681565b60085481565b6000546001600160a01b03163314611248576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811661128d5760405162461bcd60e51b81526004018080602001828103825260268152602001806114916026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008282018381101561134f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b60008261136757506000611352565b8282028284828161137457fe5b041461134f5760405162461bcd60e51b81526004018080602001828103825260218152602001806114b76021913960400191505060405180910390fd5b600061134f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506000818361147a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561143f578181015183820152602001611427565b50505050905090810190601f16801561146c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161148657fe5b049594505050505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cb882a5725c867fbbf5a99c397119e3f4b273ec879d231ecb90877ff439b726364736f6c634300070500330000000000000000000000007b6073a4471fd32c3875f11cc1bd0257e9e083ac00000000000000000000000042ed764ec17ff0bc4a0d0e6c09d1d6444233effd000000000000000000000000246dd366204fc15fd0f9e0fa23c336245414d2c1000000000000000000000000f5c55975a5c13a8fc9b78c82815ab3757ee019bf
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061011b5760003560e01c806373b2e80e116100b2578063bf3506c111610081578063e004a3d811610066578063e004a3d8146102a0578063e6c20dd1146102a8578063f2fde38b146102b05761011b565b8063bf3506c11461023b578063dbac3d3d146102615761011b565b806373b2e80e146101d757806386608326146102115780638acca092146102195780638da5cb5b146102335761011b565b806363d9df85116100ee57806363d9df851461017557806366168bd71461017d5780636ff1c9bc146101a9578063715018a6146101cf5761011b565b806307a15cd41461012057806333a2ef861461014457806343bb18ff1461014c57806348c54b9d1461016d575b600080fd5b6101286102d6565b604080516001600160a01b039092168252519081900360200190f35b6101286102e5565b61016b6004803603602081101561016257600080fd5b503515156102f4565b005b61016b61039a565b610128610a0e565b61016b6004803603604081101561019357600080fd5b506001600160a01b038135169060200135610a1d565b61016b600480360360208110156101bf57600080fd5b50356001600160a01b0316610cba565b61016b610ec4565b6101fd600480360360208110156101ed57600080fd5b50356001600160a01b0316610f7a565b604080519115158252519081900360200190f35b6101fd610f8f565b610221610f98565b60408051918252519081900360200190f35b610128610f9e565b6101fd6004803603602081101561025157600080fd5b50356001600160a01b0316610fad565b6102876004803603602081101561027757600080fd5b50356001600160a01b031661105e565b6040805192835260208301919091528051918290030190f35b6101286111d4565b6102216111e3565b61016b600480360360208110156102c657600080fd5b50356001600160a01b03166111e9565b6004546001600160a01b031681565b6003546001600160a01b031681565b6000546001600160a01b03163314610353576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6007805482151560ff19909116811790915560408051918252517f11d48e11836d1d72286877c5b0f66b9a7c76273a1a1037b299c8460a497938679181900360200190a150565b600260015414156103f2576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b600260015560075460ff1661044e576040805162461bcd60e51b815260206004820152601b60248201527f446973747269627574696f6e206973206e6f7420656e61626c65640000000000604482015290519081900360640190fd5b3360009081526006602052604090205460ff16156104b3576040805162461bcd60e51b815260206004820152600f60248201527f416c726561647920636c61696d65640000000000000000000000000000000000604482015290519081900360640190fd5b6002546040805163042e94c960e41b815233600482015290516000926001600160a01b0316916342e94c90916024808301926020929190829003018186803b1580156104fe57600080fd5b505afa158015610512573d6000803e3d6000fd5b505050506040513d602081101561052857600080fd5b505190508061057e576040805162461bcd60e51b815260206004820152601960248201527f4e6f7420612070726573616c65207061727469636970616e7400000000000000604482015290519081900360640190fd5b60008061058a3361105e565b91509150600082118061059d5750600081115b6105ee576040805162461bcd60e51b815260206004820152601060248201527f4e6f7468696e6720746f20636c61696d00000000000000000000000000000000604482015290519081900360640190fd5b600354604080516370a0823160e01b8152306004820152905184926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561063857600080fd5b505afa15801561064c573d6000803e3d6000fd5b505050506040513d602081101561066257600080fd5b505110156106b7576040805162461bcd60e51b815260206004820152601a60248201527f496e73756666696369656e7420536f6c69732062616c616e6365000000000000604482015290519081900360640190fd5b60048054604080516370a0823160e01b815230938101939093525183926001600160a01b03909216916370a08231916024808301926020929190829003018186803b15801561070557600080fd5b505afa158015610719573d6000803e3d6000fd5b505050506040513d602081101561072f57600080fd5b50511015610784576040805162461bcd60e51b815260206004820152601c60248201527f496e73756666696369656e74207374536f6c69732062616c616e636500000000604482015290519081900360640190fd5b336000908152600660205260409020805460ff191660011790558115610875576003546040805163a9059cbb60e01b81523360048201526024810185905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156107f857600080fd5b505af115801561080c573d6000803e3d6000fd5b505050506040513d602081101561082257600080fd5b5051610875576040805162461bcd60e51b815260206004820152601560248201527f536f6c6973207472616e73666572206661696c65640000000000000000000000604482015290519081900360640190fd5b80156109cb57600480546040805163a9059cbb60e01b8152339381019390935260248301849052516001600160a01b039091169163a9059cbb9160448083019260209291908290030181600087803b1580156108d057600080fd5b505af11580156108e4573d6000803e3d6000fd5b505050506040513d60208110156108fa57600080fd5b505161094d576040805162461bcd60e51b815260206004820152601760248201527f7374536f6c6973207472616e73666572206661696c6564000000000000000000604482015290519081900360640190fd5b600554604080517f45af59d300000000000000000000000000000000000000000000000000000000815233600482015290516001600160a01b03909216916345af59d39160248082019260009290919082900301818387803b1580156109b257600080fd5b505af11580156109c6573d6000803e3d6000fd5b505050505b6040805183815260208101839052815133927f9923b4306c6c030f2bdfbf156517d5983b87e15b96176da122cd4f2effa4ba7b928290030190a250506001805550565b6002546001600160a01b031681565b6000546001600160a01b03163314610a7c576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6003546001600160a01b0383811691161480610aa557506004546001600160a01b038381169116145b610af6576040805162461bcd60e51b815260206004820152600d60248201527f496e76616c696420746f6b656e00000000000000000000000000000000000000604482015290519081900360640190fd5b60008111610b4b576040805162461bcd60e51b815260206004820152601d60248201527f416d6f756e74206d7573742062652067726561746572207468616e2030000000604482015290519081900360640190fd5b604080517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526044810183905290516001600160a01b038416916323b872dd9160648083019260209291908290030181600087803b158015610bb957600080fd5b505af1158015610bcd573d6000803e3d6000fd5b505050506040513d6020811015610be357600080fd5b5051610c36576040805162461bcd60e51b815260206004820152601560248201527f546f6b656e207472616e73666572206661696c65640000000000000000000000604482015290519081900360640190fd5b6003546001600160a01b0383811691161415610c6157600854610c5990826112f5565b600855610c72565b600954610c6e90826112f5565b6009555b604080516001600160a01b03841681526020810183905281517f59062170a285eb80e8c6b8ced60428442a51910635005233fc4ce084a475845e929181900390910190a15050565b6000546001600160a01b03163314610d19576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b604080516370a0823160e01b8152306004820152905182916000916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015610d6457600080fd5b505afa158015610d78573d6000803e3d6000fd5b505050506040513d6020811015610d8e57600080fd5b5051905080610de4576040805162461bcd60e51b815260206004820152601560248201527f4e6f20746f6b656e7320746f2077697468647261770000000000000000000000604482015290519081900360640190fd5b816001600160a01b031663a9059cbb610dfb610f9e565b836040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610e4257600080fd5b505af1158015610e56573d6000803e3d6000fd5b505050506040513d6020811015610e6c57600080fd5b5051610ebf576040805162461bcd60e51b815260206004820152600f60248201527f5472616e73666572206661696c65640000000000000000000000000000000000604482015290519081900360640190fd5b505050565b6000546001600160a01b03163314610f23576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a36000805473ffffffffffffffffffffffffffffffffffffffff19169055565b60066020526000908152604090205460ff1681565b60075460ff1681565b60095481565b6000546001600160a01b031690565b6001600160a01b03811660009081526006602052604081205460ff1615610fd657506000611059565b6002546040805163042e94c960e41b81526001600160a01b038581166004830152915160009392909216916342e94c9091602480820192602092909190829003018186803b15801561102757600080fd5b505afa15801561103b573d6000803e3d6000fd5b505050506040513d602081101561105157600080fd5b505115159150505b919050565b6002546040805163042e94c960e41b81526001600160a01b0384811660048301529151600093849384939116916342e94c9091602480820192602092909190829003018186803b1580156110b157600080fd5b505afa1580156110c5573d6000803e3d6000fd5b505050506040513d60208110156110db57600080fd5b50519050806110f15760008092509250506111cf565b600254604080517f98de542100000000000000000000000000000000000000000000000000000000815290516000926001600160a01b0316916398de5421916004808301926020929190829003018186803b15801561114f57600080fd5b505afa158015611163573d6000803e3d6000fd5b505050506040513d602081101561117957600080fd5b5051905080611190576000809350935050506111cf565b6111af816111a96008548561135890919063ffffffff16565b906113b1565b93506111ca816111a96009548561135890919063ffffffff16565b925050505b915091565b6005546001600160a01b031681565b60085481565b6000546001600160a01b03163314611248576040805162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6001600160a01b03811661128d5760405162461bcd60e51b81526004018080602001828103825260268152602001806114916026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a36000805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0392909216919091179055565b60008282018381101561134f576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b90505b92915050565b60008261136757506000611352565b8282028284828161137457fe5b041461134f5760405162461bcd60e51b81526004018080602001828103825260218152602001806114b76021913960400191505060405180910390fd5b600061134f83836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506000818361147a5760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561143f578181015183820152602001611427565b50505050905090810190601f16801561146c5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161148657fe5b049594505050505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77a2646970667358221220cb882a5725c867fbbf5a99c397119e3f4b273ec879d231ecb90877ff439b726364736f6c63430007050033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007b6073a4471fd32c3875f11cc1bd0257e9e083ac00000000000000000000000042ed764ec17ff0bc4a0d0e6c09d1d6444233effd000000000000000000000000246dd366204fc15fd0f9e0fa23c336245414d2c1000000000000000000000000f5c55975a5c13a8fc9b78c82815ab3757ee019bf
-----Decoded View---------------
Arg [0] : _presaleContract (address): 0x7B6073a4471FD32C3875F11cc1Bd0257e9E083Ac
Arg [1] : _solisToken (address): 0x42ED764Ec17FF0bc4a0d0E6c09D1d6444233EfFD
Arg [2] : _stSolisToken (address): 0x246dD366204Fc15fD0f9e0fa23c336245414d2c1
Arg [3] : _luxFarmContract (address): 0xf5c55975A5c13a8fC9b78C82815Ab3757ee019Bf
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000007b6073a4471fd32c3875f11cc1bd0257e9e083ac
Arg [1] : 00000000000000000000000042ed764ec17ff0bc4a0d0e6c09d1d6444233effd
Arg [2] : 000000000000000000000000246dd366204fc15fd0f9e0fa23c336245414d2c1
Arg [3] : 000000000000000000000000f5c55975a5c13a8fc9b78c82815ab3757ee019bf
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in S
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.