Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- STOFactoryManagedUpgradeable
- Optimization enabled
- true
- Compiler version
- v0.8.29+commit.ab55807c
- Optimization runs
- 100
- EVM Version
- prague
- Verified at
- 2026-03-10T14:20:48.467782Z
Constructor Arguments
0x000000000000000000000000f02bd811d74e5b3e1866bd19e1b8451d48f58bd60000000000000000000000000000000000000000000000000000000000000000
Arg [0] (address) : 0xf02bd811d74e5b3e1866bd19e1b8451d48f58bd6
Arg [1] (address) : 0x0000000000000000000000000000000000000000
contracts/sto/factory/STOFactoryManagedUpgradeable.sol
/// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
import {Roles} from "../helpers/Roles.sol";
import {STOFactoryUpgradeable} from "./STOFactoryUpgradeable.sol";
import {Errors} from "../helpers/Errors.sol";
import {IBeacon} from "../helpers/BeaconProxy.sol";
import {ISTOToken} from "../interfaces/ISTOToken.sol";
import {AccessControlEnumerableUpgradeable, AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
import {IPriceAndSwapManager} from "../helpers/PriceAndSwapManager.sol";
/// @title STOFactoryManaged wrapper around STOFactoryUpgradeable contract to add access control and roles
/// @custom:security-contact tech@brickken.com
contract STOFactoryManagedUpgradeable is
STOFactoryUpgradeable,
AccessControlEnumerableUpgradeable
{
mapping(address tokenizer => uint256 credits)
private tokenizationCredits_OLD_SLOT;
/// @custom:oz-upgrades-unsafe-allow constructor
/// @dev constructor to set immutable variables
constructor(
address _router,
address _priceAndSwapManager
) STOFactoryUpgradeable(_router, _priceAndSwapManager) {}
/// @dev Method to initialize the contract. If further initializations are needed, the reinitializer modifier should be changed with the newer version
/// @dev future initializations will not re-set the roles and will skip the roles assignments. If contract is already initialized once, only the DEFAULT_ADMIN_ROLE can call this function.
function initialize(
address beaconToken,
address beaconEscrow,
address vault,
address admin,
address offchainSigner,
uint8 version
) external reinitializer(version) {
__AccessControlEnumerable_init();
__STOFactory_init();
if (admin == address(0)) revert Errors.NotZeroAddress();
if (
getRoleMemberCount(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE) !=
0 &&
!hasRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, _msgSender())
) revert Errors.UserIsNotAdmin(_msgSender());
if (
getRoleMemberCount(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE) == 0
) {
_grantRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, admin);
_grantRole(Roles.FACTORY_PAUSER_ROLE, admin);
_grantRole(Roles.FACTORY_OFFCHAIN_REPORTER_ROLE, offchainSigner);
}
if (vault == address(0)) revert Errors.NotZeroAddress();
brickkenVault = vault;
stoBeaconToken = beaconToken;
stoBeaconEscrow = beaconEscrow;
}
/// @dev Method to pause the factory. Only FACTORY_PAUSER_ROLE can call this function.
function pauseFactory()
external
whenNotPaused
onlyRole(Roles.FACTORY_PAUSER_ROLE)
{
_pause();
}
/// @dev Method to unpause the factory. Only FACTORY_PAUSER_ROLE can call this function.
function unpauseFactory()
external
whenPaused
onlyRole(Roles.FACTORY_PAUSER_ROLE)
{
_unpause();
}
/// @dev Method to deploy a new tokenization (escrow + token).
/// @param config Configuration of the token to be deployed,
/// @param offchainReport the offchain report struct
/// @param permit the permit signature struct if any
function newTokenization(
TokenizationConfig calldata config,
OffchainReport calldata offchainReport,
PermitStruct calldata permit
) external whenNotPaused {
/// By default each new token and escrow is owned by Brickken. Adminship can be handed over at any moment.
(address stoToken, address stoEscrow) = _newTokenization(
config,
offchainReport,
permit,
getRoleMember(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE, 0) // admin
);
// Setup the escrow as a valid minter
ISTOToken(stoToken).addMinter(stoEscrow);
// Renounce being minter admin, permission given termporary to set the escrow as a minter
ISTOToken(stoToken).renounceRole(
Roles.TOKEN_MINTER_ADMIN_ROLE,
address(this)
);
emit NewTokenization(idSTOs, stoTokens[idSTOs], stoEscrows[idSTOs]);
}
/// @dev Method to change configured parameters within the contract. Only DEFAULT_ADMIN_ROLE can call this function.
/// @param vault this will change where fees are sent
/// @param beaconToken this will change the beacon token used for new tokenizations
/// @param beaconEscrow this will change the beacon escrow used for new tokenizations
/// @param allowedEscrows escrows whose status must be changed in the PriceAndSwapManager
/// @param allowedEscrowsStatuses statuses to be applied to the above escrows
function changeConfig(
address vault,
address beaconToken,
address beaconEscrow,
address[] calldata allowedEscrows,
bool[] calldata allowedEscrowsStatuses
) external onlyRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE) {
uint256 length = allowedEscrows.length;
if (length != allowedEscrowsStatuses.length)
revert Errors.LengthsMismatch();
_changeConfig(vault, beaconToken, beaconEscrow);
for (uint256 i; i < length; ) {
if (allowedEscrows[i] == address(0)) revert Errors.NotZeroAddress();
IPriceAndSwapManager(priceAndSwapManager).setAllowed(
allowedEscrows[i],
allowedEscrowsStatuses[i]
);
unchecked {
++i;
}
}
}
/// @dev Method to validate the offchain report
/// @param offchainReport Configuration of the offchain report
function _validateOffchainReport(
OffchainReport memory offchainReport
) internal view override returns (address signer) {
signer = super._validateOffchainReport(offchainReport);
if (!hasRole(Roles.FACTORY_OFFCHAIN_REPORTER_ROLE, signer)) {
revert Errors.InvalidSigner(signer);
}
}
/// @dev Override OpenZeppelin contracts function to restrict upgradeability to only accounts with the DEFAULT_ADMIN_ROLE
function _authorizeUpgrade(
address newImplementation
)
internal
view
override
onlyRole(AccessControlUpgradeable.DEFAULT_ADMIN_ROLE)
{}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/structs/EnumerableSetUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSetUpgradeable {
// 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;
if (lastIndex != toDeleteIndex) {
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] = valueIndex; // Replace lastValue's index to valueIndex
}
// 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) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
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 in 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);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// 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(uint160(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(uint160(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(uint160(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(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// 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 in 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));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
lib/openzeppelin-contracts-upgradeable/contracts/proxy/beacon/IBeaconUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
lib/openzeppelin-contracts/contracts/utils/math/Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
contracts/sto/interfaces/IPriceAndSwapManager.sol
// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
import { ISTOToken } from "./ISTOToken.sol";
import { IChainlinkPriceFeed } from "./ChainlinkInterfaces.sol";
import { IUniswapV3Router } from "./UniswapInterfaces.sol";
interface IPriceAndSwapManager {
/// @dev auxiliary struct referring to a specific offering and its details
struct OfferingDetails {
bool isEnded; // Whether the offering is still active or not
uint256 hardCap; // configured hardcap to be reached
uint256 minTicket; // configured minimum ticket that can be invested
uint256 maxTicket; // configured maximum ticket that can be invested
uint256 priceInUSD; // configured price in USD of one token with 18 decimals
uint256 raisedAmount; // how many USD have been raised so far
uint256 issuanceIndex; // the index of the current issuance
}
/// @dev auxiliary struct referring to an investor of a specific offering.
struct UserDetails {
bool isUserInvestor; // whether the user is already an investor or not
uint256 userAmountOfPaymentTokens; // how many paymentToken tokens the user is putting in
}
/// @dev auxiliary struct with all the details of the token used by the investor in the offering.
struct TokenUsedDetails {
bool isTokenWhitelisted; // whether the used token is whitelisted in the escrow contract
address tokenAddress; // the used token address
uint256 amountOfTokens; // the amount of tokens being sent by the user
uint256 whitelistedTokenFeesOnSwap; // fees so that the right Uniswap pool can be selected
}
/// @dev auxiliary struct with all the details about the escrow from where the requests are coming from.
struct EscrowDetails {
address paymentToken; // the payment token configured in the escrow
uint256 twapInterval; // TWAP interval to use in price validation of the payment token
ISTOToken stoRelatedToken; // the address of the token related to the tokenization
IChainlinkPriceFeed paymentTokenOracle; // oracle address to retrieve paymentToken price
IUniswapV3Router router; // Uniswap v3 router to be used for swaps
}
/// @dev auxiliary struct with all the details about Uniswap pool of the token used (see TokenUsedDetails above).
/// @dev This contains some redundant information with TokenUsedDetails but is not used concurrently with the TokenUsedDetails
struct PoolDetails {
address tokenAddress; // Token address being used for buying a ticket
address paymentToken; // paymentToken configured in the escrow
IUniswapV3Router router; // Uniswap v3 router used
uint24 fees; // fees to select the right Uniswap v3 pool
}
/// @dev Method to estimate the amount of tokens that the user will get by participating in a specifing offering according to the current offering details.
/// @param caller the user buying a ticket in the offering
/// @param offeringDetails current details of the offering in which the user wish to participate
/// @param userDetails whether the user is currently an investor and how many payment tokens is using
/// @param tokenUsedDetails the details of the token being used by the investor to buy a ticket
/// @param escrowDetails the details of the escrow calling this contract for every request
/// @return expectedAmount the expected amount of tokens bought by the user
function getEstimationSTOToken(
address caller,
OfferingDetails calldata offeringDetails,
UserDetails calldata userDetails,
TokenUsedDetails calldata tokenUsedDetails,
EscrowDetails calldata escrowDetails
) external view returns (uint256 expectedAmount);
/// @dev Method to retrieve the USD price of the paymentToken through its paymentTokenOracle with 18 decimals of precision
/// @param paymentTokenOracle the oracle of the paymentToken to be priced
/// @param twapInterval what twap interval should be used
/// @return the USD price of the paymenToken in USD with 18 decimals of precision
function getUSDPriceOfPaymentToken(IChainlinkPriceFeed paymentTokenOracle, uint256 twapInterval) external view returns (uint256);
/// @dev Method to retrieve the price of a given token used by the user in terms of paymentToken, provided that a Uniswap v3 pool of such token against the paymentToken exists.
/// @param poolDetails the Uniswap v3 pool of the token used against the paymentToken
/// @param twapInterval what twap interval should be used
/// @return price the price of the token used against the paymenToken with 18 decimals of precision
function getPriceInPaymentToken(
PoolDetails calldata poolDetails,
uint256 twapInterval
) external view returns (uint256 price);
/// @dev Method to swap a given token for paymentToken using an existing Uniswap v3 pool
/// @param poolDetails the Uniswap v3 pool of the token used against the paymentToken
/// @param tokenAmount the amount of tokens being swapped
/// @param expectedAmount the expected amount of paymentToken to control slippage
function swapTokensForPaymentTokens(
PoolDetails calldata poolDetails,
uint256 tokenAmount,
uint256 expectedAmount
) external;
/// @dev Method to reset all allowances in case the Uniswap router must be changed in the escrow contract
/// @param oldAddress the old Uniswap router
/// @param newAddress the new Uniswap router
/// @param tokensERC20 the list of tokens whose allowances must be reset
function resetAllowances(
address oldAddress,
address newAddress,
address[] memory tokensERC20
) external;
/// @dev Method restricted in access to be called by the factory to allow/disallow specific escrows from calling this contract
/// @param toBeSet the address of the escrow to allow/disallow
/// @param status whether to allow it or not
function setAllowed(address toBeSet, bool status) external;
}
lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
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));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
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));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
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);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
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");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @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).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20MetadataUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/IERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165Upgradeable {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
contracts/sto/interfaces/ISTOToken.sol
/// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
import { IERC20MetadataUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol";
interface ISTOToken is IERC20MetadataUpgradeable {
function addMinter(address newMinter) external;
function hasRole(bytes32 role, address account) external view returns (bool);
function renounceRole(bytes32 role, address account) external;
function mint(address to, uint256 amount) external;
function mintBatch(address[] calldata _addresess, uint256[] calldata _amounts) external;
function supplyCap() external view returns (uint224);
function whitelist_OLD_SLOT(address user) external view returns(bool);
}
lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/IERC20PermitUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20PermitUpgradeable {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.0;
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../ERC1967/ERC1967UpgradeUpgradeable.sol";
import "./Initializable.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal onlyInitializing {
}
function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
}
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall");
_;
}
/**
* @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual override notDelegated returns (bytes32) {
return _IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeTo(address newImplementation) public virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
contracts/sto/interfaces/UniswapInterfaces.sol
/// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
interface IUniswapV3Router {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
function factory() external view returns(address);
}
interface IUniswapV3Factory {
function getPool(address, address, uint24) external view returns(address pool);
}
interface IUniswapV3Pair {
function observe(
uint32[] calldata secondsAgos
)
external
view
returns (
int56[] memory tickCumulatives,
uint160[] memory secondsPerLiquidityCumulativeX128s
);
function token0() external view returns (address);
function token1() external view returns (address);
}
interface IUniswapV2Pair {
function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
}
lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/Address.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
lib/openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
function __Pausable_init() internal onlyInitializing {
__Pausable_init_unchained();
}
function __Pausable_init_unchained() internal onlyInitializing {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
require(paused(), "Pausable: not paused");
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/utils/SafeERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20Upgradeable.sol";
import "../extensions/IERC20PermitUpgradeable.sol";
import "../../../utils/AddressUpgradeable.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20Upgradeable {
using AddressUpgradeable for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20Upgradeable token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20Upgradeable token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20Upgradeable 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));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20Upgradeable 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);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20PermitUpgradeable 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");
}
/**
* @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(IERC20Upgradeable token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @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).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20Upgradeable token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));
}
}
lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}
lib/openzeppelin-contracts-upgradeable/contracts/access/IAccessControlEnumerableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
pragma solidity ^0.8.0;
import "./IAccessControlUpgradeable.sol";
/**
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
*/
interface IAccessControlEnumerableUpgradeable is IAccessControlUpgradeable {
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) external view returns (address);
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) external view returns (uint256);
}
lib/openzeppelin-contracts/contracts/proxy/Proxy.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)
pragma solidity ^0.8.0;
/**
* @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
* instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
* be specified by overriding the virtual {_implementation} function.
*
* Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
* different contract through the {_delegate} function.
*
* The success and return data of the delegated call will be returned back to the caller of the proxy.
*/
abstract contract Proxy {
/**
* @dev Delegates the current call to `implementation`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _delegate(address implementation) internal virtual {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
* and {_fallback} should delegate.
*/
function _implementation() internal view virtual returns (address);
/**
* @dev Delegates the current call to the address returned by `_implementation()`.
*
* This function does not return to its internal call site, it will return directly to the external caller.
*/
function _fallback() internal virtual {
_beforeFallback();
_delegate(_implementation());
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
* function in the contract matches the call data.
*/
fallback() external payable virtual {
_fallback();
}
/**
* @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
* is empty.
*/
receive() external payable virtual {
_fallback();
}
/**
* @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
* call, or as part of the Solidity `fallback` or `receive` functions.
*
* If overridden should call `super._beforeFallback()`.
*/
function _beforeFallback() internal virtual {}
}
lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
lib/openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @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);
/**
* @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 `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, 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 `from` to `to` 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 from, address to, uint256 amount) external returns (bool);
}
lib/openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/ContextUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
function __Ownable_init() internal onlyInitializing {
__Ownable_init_unchained();
}
function __Ownable_init_unchained() internal onlyInitializing {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/math/MathUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUpgradeable {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
contracts/sto/helpers/Roles.sol
// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
library Roles {
// DEFAULT_ADMIN_ROLE = grant/revoke roles (brickken)
//
// This role operated by brickken can grant/revoke any role in the system. Specifically it
// can also perform some special actions. Brickken operates through Gnosis Safe multisig for every
// operation.
//
// On the escrow:
//
// - change issuer, if issuer wallet gets compromised
// - change payment token, if issuer desires to change the asset used in the offering
// - change router, if unexpected circumstances forces us to change Uniswap v3 router
// - change price and swap manager, if unexpected circumstances forces us to change the contract logic
// - change treasury address, if brickken wants to change where success fees are sent
//
// Other roles description:
//
// - DEFAULT_ADMIN_ROLE = grant/revoke roles (brickken)
// - ESCROW_WITHDRAW_ROLE = who can withdraw / partially withdraw to issuer (issuer);
// - ESCROW_NEW_OFFERING_ROLE = starts a new offering (issuer);
// - ESCROW_OFFERING_FINALIZER_ROLE = finalize an offering (brickken, issuer);
// - ESCROW_ERC20WHITELIST_ROLE = add/remove ERC20 from whitelist (brickken, issuer);
// - ESCROW_OFFCHAIN_REPORTER_ROLE = report offchain USD tickets for current offering (issuer)
//
// On the token:
//
// - change issuer, if issuer wallet gets compromised
// - change payment token, if issuer desires to change the asset used to distribute dividends
// - change max supply, if there are extensions in the STO equities amount, this will conflict if max supply has been already minted
//
// Other roles description:
//
// - DEFAULT_ADMIN_ROLE = grant/revoke roles (brickken)
// - TOKEN_URL_ROLE = change url (brickken,issuer);
// - TOKEN_DIVIDEND_DISTRIBUTOR_ROLE = distribute dividends (issuer);
// - TOKEN_MINTER_ROLE = mint new tokens (issuer, escrow contract);
// - TOKEN_MINTER_ADMIN_ROLE = add/remove minters (issuer);
// - TOKEN_WHITELIST_ADMIN_ROLE = change investors whitelist (issuer);
// - TOKEN_WHITELIST_ROLE = whether the user is whitelisted or not (issuer);
// - TOKEN_CONFISCATE_EXECUTOR_ROLE = execute confiscation (brickken);
// - TOKEN_CONFISCATE_ADMIN_ROLE = pause / unpause or disable confiscation (brickken);
//
// On the factory:
//
// Brickken is the owner and sole operator of the factory so it has full permissions on it
//
// Other roles description:
//
// - DEFAULT_ADMIN_ROLE = grant/revoke roles (brickken)
// - FACTORY_PAUSER_ROLE = pause / unpause factory (brickken);
// - FACTORY_OFFCHAIN_REPORTER_ROLE = can sign offchain reports;
// 0x914095fa3ba2bffbd4003cbfb530f542f1b7f4f99ba858dc177f6f248873b68a
bytes32 public constant FACTORY_PAUSER_ROLE =
keccak256(abi.encode("FACTORY_PAUSER_ROLE")); // pause / unpause factory (brickken);
// 0x628cdeda042a2a7d76a8884d4cf6ce99bee316818ea211c803a1e1941412a9d3
bytes32 public constant FACTORY_OFFCHAIN_REPORTER_ROLE =
keccak256(abi.encode("FACTORY_OFFCHAIN_REPORTER_ROLE")); // can sign offchain reports;
// 0x7e634896b27e79a960e89ae00f5b87ef365e84b0543277e0eb9d018a47e752f1
bytes32 public constant ESCROW_WITHDRAW_ROLE =
keccak256(abi.encode("ESCROW_WITHDRAW_ROLE")); // who can partially withdraw to issuer (issuer);
// 0x373a3fc4287a1339d038c211cc53ad6aed3b80e2257f4889df84173c57e41680
bytes32 public constant ESCROW_NEW_OFFERING_ROLE =
keccak256(abi.encode("ESCROW_NEW_OFFERING_ROLE")); // starts a new offering (issuer);
// 0x2b797e16dca25f832ef5eecf31aa514d12de6a1d3acdb0e8adae46f707e2d689
bytes32 public constant ESCROW_ERC20WHITELIST_ROLE =
keccak256(abi.encode("ESCROW_ERC20WHITELIST_ROLE")); // add/remove ERC20 from whitelist (brickken, issuer);
// 0xb33eb5fac4455e424b782c8f7380698677b4c84586b4d8f52049804c691485d4
bytes32 public constant ESCROW_OFFCHAIN_REPORTER_ROLE =
keccak256(abi.encode("ESCROW_OFFCHAIN_REPORTER_ROLE")); // report offchain tickets (issuer);
// 0x5bff9b7fe86d1ecb8e388c7b1441e17acc34d11a5ea2f7d940ec3e3ce4886499
bytes32 public constant ESCROW_OFFERING_FINALIZER_ROLE =
keccak256(abi.encode("ESCROW_OFFERING_FINALIZER_ROLE")); // finalize an offering (brickken, issuer);
// 0x4e2d8cfba5434336d245506de15fea51aa5dbefbf272b26dec4a6d6cf5be64bb
bytes32 public constant TOKEN_MINTER_ADMIN_ROLE =
keccak256(abi.encode("TOKEN_MINTER_ADMIN_ROLE")); // add/remove minters (issuer);
// 0x8d47e3ef6c6edd6d0cd062221e938c7813759ba93d9dabe49168cbc8e44c0758
bytes32 public constant TOKEN_WHITELIST_ADMIN_ROLE =
keccak256(abi.encode("TOKEN_WHITELIST_ADMIN_ROLE")); // change investors whitelist (issuer);
// 0xf740e572f2d7bd1702c994cd1a49022e4ee57025012d0f6b14521717383b58e2
bytes32 public constant TOKEN_CONFISCATE_ADMIN_ROLE =
keccak256(abi.encode("TOKEN_CONFISCATE_ADMIN_ROLE")); // pause / unpause or disable confiscation (brickken);
// 0x1049b81d2f35f188cbe4711fe8f0ee41a5deefb51b0bfd57490d0252047edf69
bytes32 public constant TOKEN_URL_ROLE =
keccak256(abi.encode("TOKEN_URL_ROLE")); // change url (brickken,issuer);
// 0xafece24e20488bd8efc86502ef37bf1d0863acdcafe60cff7122dc1ee40280c2
bytes32 public constant TOKEN_MINTER_ROLE =
keccak256(abi.encode("TOKEN_MINTER_ROLE")); // mint new tokens (issuer, escrow contract);
// 0xe7fd28cbd94ed64bb8cca17950a38aed85f0745ec696947c8e31b86025ae980a
bytes32 public constant TOKEN_WHITELIST_ROLE =
keccak256(abi.encode("TOKEN_WHITELIST_ROLE")); // whether the user is whitelisted or not (issuer);
// 0x715da9afc9135274cab1c53398817af927b44460ab45f4383352ea02e368b76e
bytes32 public constant TOKEN_CONFISCATE_EXECUTOR_ROLE =
keccak256(abi.encode("TOKEN_CONFISCATE_EXECUTOR_ROLE")); // execute confiscation (brickken);
// 0x8908c8648724bfdf4166023b8e574b3a283c453f044b1b7f3937995d4cd084f3
bytes32 public constant TOKEN_DIVIDEND_DISTRIBUTOR_ROLE =
keccak256(abi.encode("TOKEN_DIVIDEND_DISTRIBUTOR_ROLE")); // distribute dividends (issuer);
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 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://consensys.net/diligence/blog/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} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
contracts/sto/interfaces/ISTOFactoryUpgradeable.sol
/// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
interface ISTOFactoryUpgradeable {
/// @dev Struct with tokenization config
/// @param url URI for offchain records stored in IPFS referring to one specific tokenization
/// @param name Name of the STOToken
/// @param symbol Symbol of the STOToken
/// @param supplyCap Cap on the supply of the STOToken, 0 if unlimited supply (unlimited up to type(uint224).max because of checkpoints feature)
/// @param paymentToken Token used to denominate issuer's withdraw on succesfull tokenization
/// @param paymentTokenOracle Chainlink oracle used to retrieve price of paymentToken
/// @param paymentTokenOracleUnused explicitly set to true whenever paymentTokenOracle is allowed to be zero
/// @param preMints Amounts of the STOToken to be minted to each initial holder
/// @param initialHolders Wallets of the initial holders of the STOToken
struct TokenizationConfig {
string url;
string name;
string symbol;
uint224 supplyCap;
address paymentToken;
address paymentTokenOracle;
bool paymentTokenOracleUnused;
uint256[] preMints;
address[] initialHolders;
}
/// @dev Struct with Offchain Reporting config
/// @param token Token used to pay tokenization fees
/// @param tokenAmount Amount of token used to pay tokenization fees
/// @param spender Wallet address of the fees payer
/// @param issuer Wallet address of the issuer
/// @param deadline Unix timestamp of the report signature expiration
/// @param nonce nonce of the offchain reporter address
/// @param signature Bytes resulting of the offchain report signature
struct OffchainReport {
address token;
uint256 tokenAmount;
address spender;
address issuer;
uint256 deadline;
uint256 nonce;
bytes signature;
}
/// @dev Struct with permit signature
/// @param deadline Unix timestamp of the permit signature expiration
/// @param signer address of the permit signer
/// @param spender address of the spender
/// @param amount amount of the permit signature
/// @param v v of the permit signature
/// @param r r of the permit signature
/// @param s s of the permit signature
struct PermitStruct {
uint256 deadline;
address signer;
address spender;
uint256 amount;
uint8 v;
bytes32 r;
bytes32 s;
}
/// @dev Event emitted when a new STO is created
/// @param id ID of the STO
/// @param token smart contract address of the STOToken
/// @param escrow smart contract address of the STOEscrow
event NewTokenization(
uint256 indexed id,
address indexed token,
address indexed escrow
);
/// @dev Event emitted when fees are charged for each new tokenization
/// @param issuer wallet address of the issuer
/// @param token token used to pay the fee, usually BKN
/// @param amount Amount of fees charged
event ChargeFee(address indexed issuer, address token, uint256 amount);
function pauseFactory() external;
/// @dev Method to unpause the factory. Only FACTORY_PAUSER_ROLE can call this function.
function unpauseFactory() external;
/// @dev Method to deploy a new tokenization (escrow + token).
/// @param config Configuration of the token to be deployed
/// @param offchainReport the offchain report struct
/// @param permit the permit signature struct if any
function newTokenization(
TokenizationConfig calldata config,
OffchainReport calldata offchainReport,
PermitStruct calldata permit
) external;
/// @dev Method to change configured parameters within the contract. Only DEFAULT_ADMIN_ROLE can call this function.
/// @param vault this will change where fees are sent
/// @param beaconToken this will change the beacon token used for new tokenizations
/// @param beaconEscrow this will change the beacon escrow used for new tokenizations
/// @param allowedEscrows escrows whose status must be changed in the PriceAndSwapManager
/// @param allowedEscrowsStatuses statuses to be applied to the above escrows
function changeConfig(
address vault,
address beaconToken,
address beaconEscrow,
address[] calldata allowedEscrows,
bool[] calldata allowedEscrowsStatuses
) external;
/// @dev Public method to calculate how much fees are going to be paid
/// @param offchainReport offchain report
/// @return amountToPay amount of tokens to be paid and signer address
function getFees(
OffchainReport calldata offchainReport
) external view returns (uint256 amountToPay, address signer);
/// @dev get the implementation address behind the proxy
/// @return the implementation address
function getImplementation() external view returns (address);
/// @dev get the nonce of the offchain price signer to be used
/// @param owner the address of the price offchain signer
/// @return the nonce to be used
function nonces(address owner) external view returns (uint256);
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/ContextUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
import "../proxy/utils/Initializable.sol";
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract ContextUpgradeable is Initializable {
function __Context_init() internal onlyInitializing {
}
function __Context_init_unchained() internal onlyInitializing {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlEnumerableUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
pragma solidity ^0.8.0;
import "./IAccessControlEnumerableUpgradeable.sol";
import "./AccessControlUpgradeable.sol";
import "../utils/structs/EnumerableSetUpgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Extension of {AccessControl} that allows enumerating the members of each role.
*/
abstract contract AccessControlEnumerableUpgradeable is Initializable, IAccessControlEnumerableUpgradeable, AccessControlUpgradeable {
function __AccessControlEnumerable_init() internal onlyInitializing {
}
function __AccessControlEnumerable_init_unchained() internal onlyInitializing {
}
using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;
mapping(bytes32 => EnumerableSetUpgradeable.AddressSet) private _roleMembers;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerableUpgradeable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view virtual override returns (address) {
return _roleMembers[role].at(index);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view virtual override returns (uint256) {
return _roleMembers[role].length();
}
/**
* @dev Overload {_grantRole} to track enumerable memberships
*/
function _grantRole(bytes32 role, address account) internal virtual override {
super._grantRole(role, account);
_roleMembers[role].add(account);
}
/**
* @dev Overload {_revokeRole} to track enumerable memberships
*/
function _revokeRole(bytes32 role, address account) internal virtual override {
super._revokeRole(role, account);
_roleMembers[role].remove(account);
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
lib/openzeppelin-contracts/contracts/interfaces/IERC1967.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}
lib/openzeppelin-contracts-upgradeable/contracts/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeaconUpgradeable.sol";
import "../../interfaces/IERC1967Upgradeable.sol";
import "../../interfaces/draft-IERC1822Upgradeable.sol";
import "../../utils/AddressUpgradeable.sol";
import "../../utils/StorageSlotUpgradeable.sol";
import "../utils/Initializable.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable {
function __ERC1967Upgrade_init() internal onlyInitializing {
}
function __ERC1967Upgrade_init_unchained() internal onlyInitializing {
}
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
contracts/sto/factory/STOFactoryUpgradeable.sol
/// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
import {Errors} from "../helpers/Errors.sol";
import {BeaconProxy, IBeacon} from "../helpers/BeaconProxy.sol";
import {Roles} from "../helpers/Roles.sol";
import {ISTOToken} from "../interfaces/ISTOToken.sol";
import {IPriceAndSwapManager} from "../helpers/PriceAndSwapManager.sol";
import {ISTOFactoryUpgradeable} from "../interfaces/ISTOFactoryUpgradeable.sol";
import {IUniswapV2Pair, IUniswapV3Router} from "../interfaces/UniswapInterfaces.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {MathUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/math/MathUpgradeable.sol";
import {ECDSAUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
import {AddressUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol";
import {SafeERC20Upgradeable, IERC20Upgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol";
import {IERC20PermitUpgradeable} from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol";
import {AccessControlEnumerableUpgradeable, AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol";
/// @title STOFactory
/// @custom:security-contact tech@brickken.com
abstract contract STOFactoryUpgradeable is
ISTOFactoryUpgradeable,
Initializable,
OwnableUpgradeable,
PausableUpgradeable,
UUPSUpgradeable
{
using AddressUpgradeable for address;
using MathUpgradeable for uint256;
// EIP712 Domain parameters
bytes32 public constant HASH_NAME = keccak256(bytes("OffchainReport"));
bytes32 public constant HASH_VERSION = keccak256(bytes("1.0"));
bytes32 private constant _OFFCHAIN_PRICE_REPORT_TYPE_HASH =
keccak256(
"OffchainReport(address token,uint256 tokenAmount,address spender,address issuer,uint256 deadline,uint256 nonce)"
); // TypeHash of EIP712 Domain
bytes32 private constant _TYPE_HASH =
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);
/// Replacing old variables for immutable constants, to save gas.
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address public immutable priceAndSwapManager;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable bkn_OLD_SLOT_2;
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address public immutable router;
address private bkn_OLD_SLOT; // Brickken Token Address. Keep for back compatibility. Deprecated slot. Ignore.
address public brickkenVault; // Brickken Vault Address
address public stoBeaconToken; // Beacon Token Address
address public stoBeaconEscrow; // Beacon Escrow Address
uint256 private priceInBKN_OLD_SLOT; // Price of STO in BKN, this is used as a fixed amount of BKN to pay if priceInUSD is 0
uint256 private priceInUSD_OLD_SLOT; // Price of STO in USD, used to calculate how many BKNs are charged based on oracle price
uint256 public idSTOs; // STO ID
// Mapping of STOTokens and STOEscrows addresses to their respective STO IDs
mapping(uint256 id => address tokenAddress) public stoTokens;
mapping(uint256 id => address escrowAddress) public stoEscrows;
mapping(address whitelistedAddress => bool status)
internal whitelist_OLD_SLOT; // Keep for back compatibility. Deprecated slot. Ignore.
mapping(address => uint256) private _nonces;
uint256 private bknPriceTWAPInterval_OLD_SLOT; // Time window used to invalidate the BKN price from the liquidity pool
/// @custom:oz-upgrades-unsafe-allow constructor
/// @dev constructor to set immutable values
constructor(address _router, address _priceAndSwapManager) {
if (_router == address(0)) revert Errors.NotZeroAddress();
bkn_OLD_SLOT_2 = address(0);
router = _router;
priceAndSwapManager = _priceAndSwapManager;
_disableInitializers();
}
/// @dev Public method to calculate how much fees are going to be paid
/// @param offchainReport offchain report
/// @return amountToPay amount of tokens to be paid and signer address
function getFees(
OffchainReport calldata offchainReport
) public view returns (uint256 amountToPay, address signer) {
signer = _validateOffchainReport(offchainReport);
amountToPay = offchainReport.tokenAmount;
}
/// @dev get the implementation address behind the proxy
/// @return the implementation address
function getImplementation() external view returns (address) {
return _getImplementation();
}
function nonces(address owner) external view returns (uint256) {
return _nonces[owner];
}
// INTERNAL / PRIVATE FUNCTIONS
/// @dev Internal method initialize the contract. To be called by a parent contract.
function __STOFactory_init() internal {
__Ownable_init();
__Pausable_init();
__UUPSUpgradeable_init();
}
/// @dev Method to change configured parameters within the contract.
/// @param vault this will change where fees are sent
/// @param beaconToken this will change the beacon token used for new tokenizations
/// @param beaconEscrow this will change the beacon escrow used for new tokenizations
function _changeConfig(
address vault,
address beaconToken,
address beaconEscrow
) internal {
if (
vault == address(0) ||
beaconToken == address(0) ||
beaconEscrow == address(0)
) revert Errors.NotZeroAddress();
brickkenVault = vault;
stoBeaconToken = beaconToken;
stoBeaconEscrow = beaconEscrow;
}
/// @dev Method to deploy a new tokenization (escrow + token)
/// @param config Configuration of the token to be deployed
/// @param offchainReport the offchain report struct
/// @param permit the permit signature struct if any
/// @param admin Who is going to be the DEFAULT_ADMIN_ROLE account both for escrow and token
/// @return addresses of escrow and token
function _newTokenization(
TokenizationConfig calldata config,
OffchainReport calldata offchainReport,
PermitStruct calldata permit,
address admin
) internal returns (address, address) {
{
_chargeFee(offchainReport, permit);
uint256 length = config.preMints.length;
if (config.initialHolders.length != length)
revert Errors.LengthsMismatch();
uint256 totalPremint;
for (uint256 i = 0; i < length; ) {
totalPremint += config.preMints[i];
unchecked {
++i;
}
}
if (config.supplyCap != 0 && totalPremint > config.supplyCap)
revert Errors.PremintGreaterThanMaxSupply();
// Due to Checkpoints feature, uint224.max is the max supply
if (totalPremint > type(uint224).max)
revert Errors.SupplyCapExceeded();
++idSTOs;
}
stoTokens[idSTOs] = address(
new BeaconProxy(
stoBeaconToken,
admin,
abi.encodeWithSignature(
"initialize((string,string,string,uint224,address,address,bool,uint256[],address[]),address,address,uint8)",
config,
offchainReport.issuer,
admin,
2
)
)
);
stoEscrows[idSTOs] = address(
new BeaconProxy(
stoBeaconEscrow,
admin,
abi.encodeWithSignature(
"initialize(address,address,address,address,address,address,bool,address,address,uint8)",
stoTokens[idSTOs],
offchainReport.issuer,
admin,
config.paymentToken,
router,
config.paymentTokenOracle,
config.paymentTokenOracleUnused,
brickkenVault,
priceAndSwapManager,
2
)
)
);
IPriceAndSwapManager(priceAndSwapManager).setAllowed(
stoEscrows[idSTOs],
true
);
return (stoTokens[idSTOs], stoEscrows[idSTOs]);
}
/// @dev Internal method to charge the fee given the offchain report.
/// @param offchainReport the offchain report struct
function _chargeFee(
OffchainReport calldata offchainReport,
PermitStruct calldata permit
) internal {
(uint256 amountToPay, address signer) = getFees(offchainReport);
_useNonce(signer);
address tokenAddress = offchainReport.token;
/// Finally is there any positive amount of BKN to be transferred, transfer them
if (amountToPay > 0) {
if (permit.deadline > 0)
IERC20PermitUpgradeable(tokenAddress).permit(
permit.signer,
permit.spender,
permit.amount,
permit.deadline,
permit.v,
permit.r,
permit.s
);
SafeERC20Upgradeable.safeTransferFrom(
IERC20Upgradeable(tokenAddress),
offchainReport.spender,
brickkenVault,
amountToPay
);
emit ChargeFee(offchainReport.spender, tokenAddress, amountToPay);
}
}
/// @dev Method to validate the offchain report
/// @param offchainReport Configuration of the offchain report
function _validateOffchainReport(
OffchainReport memory offchainReport
) internal view virtual returns (address signer) {
uint256 deadline = offchainReport.deadline;
if (block.timestamp > deadline) {
revert Errors.ExpiredSignature(deadline, block.timestamp);
}
bytes32 structHash = keccak256(
abi.encode(
_OFFCHAIN_PRICE_REPORT_TYPE_HASH,
offchainReport.token,
offchainReport.tokenAmount,
offchainReport.spender,
offchainReport.issuer,
deadline,
offchainReport.nonce
)
);
bytes32 hash = _hashTypedDataV4(structHash);
signer = ECDSAUpgradeable.recover(hash, offchainReport.signature);
}
/// INTERNAL FUNCTIONS FOR EIP712 DOMAIN
function _hashTypedDataV4(
bytes32 structHash
) internal view virtual returns (bytes32) {
return
ECDSAUpgradeable.toTypedDataHash(_domainSeparatorV4(), structHash);
}
function _domainSeparatorV4() internal view returns (bytes32) {
return _buildDomainSeparator(_TYPE_HASH, HASH_NAME, HASH_VERSION);
}
function _buildDomainSeparator(
bytes32 typeHash,
bytes32 nameHash,
bytes32 versionHash
) private view returns (bytes32) {
return
keccak256(
abi.encode(
typeHash,
nameHash,
versionHash,
block.chainid,
address(this)
)
);
}
function _useNonce(address owner) internal returns (uint256) {
// For each account, the nonce has an initial value of 0, can only be incremented by one, and cannot be
// decremented or reset. This guarantees that the nonce never overflows.
unchecked {
// It is important to do x++ and not ++x here.
return _nonces[owner]++;
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[38] private __gap;
}
lib/openzeppelin-contracts-upgradeable/contracts/access/IAccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControlUpgradeable {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/ECDSAUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.0;
import "../StringsUpgradeable.sol";
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSAUpgradeable {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV // Deprecated in v4.8
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return; // no error: do nothing
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature` or error string. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
/// @solidity memory-safe-assembly
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {toEthSignedMessageHash} on it.
*/
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*
* _Available since v4.2._
*/
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*
* _Available since v4.3._
*/
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
// signatures from current libraries generate a unique signature with an s-value in the lower half order.
//
// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
// these malleable signatures as well.
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
// If the signature is valid (and not malleable), return the signer address
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
/**
* @dev Returns an Ethereum Signed Message, created from a `hash`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
// 32 is the length in bytes of hash,
// enforced by the type signature above
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
/**
* @dev Returns an Ethereum Signed Message, created from `s`. This
* produces hash corresponding to the one signed with the
* https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
* JSON-RPC method as part of EIP-191.
*
* See {recover}.
*/
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", StringsUpgradeable.toString(s.length), s));
}
/**
* @dev Returns an Ethereum Signed Typed Data, created from a
* `domainSeparator` and a `structHash`. This produces hash corresponding
* to the one signed with the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
* JSON-RPC method as part of EIP-712.
*
* See {recover}.
*/
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
/**
* @dev Returns an Ethereum Signed Data with intended validator, created from a
* `validator` and `data` according to the version 0 of EIP-191.
*
* See {recover}.
*/
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)
pragma solidity ^0.8.2;
import "../beacon/IBeacon.sol";
import "../../interfaces/IERC1967.sol";
import "../../interfaces/draft-IERC1822.sol";
import "../../utils/Address.sol";
import "../../utils/StorageSlot.sol";
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*/
abstract contract ERC1967Upgrade is IERC1967 {
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {
// Upgrades from old implementations will perform a rollback test. This test requires the new
// implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing
// this special case will break upgrade paths from old UUPS implementation to new ones.
if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {
_setImplementation(newImplementation);
} else {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID");
} catch {
revert("ERC1967Upgrade: new implementation is not UUPS");
}
_upgradeToAndCall(newImplementation, data, forceCall);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
Address.isContract(IBeacon(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
}
}
}
lib/openzeppelin-contracts-upgradeable/contracts/interfaces/IERC1967Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*
* _Available since v4.8.3._
*/
interface IERC1967Upgradeable {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}
lib/openzeppelin-contracts/contracts/utils/Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
lib/openzeppelin-contracts-upgradeable/contracts/access/AccessControlUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControlUpgradeable.sol";
import "../utils/ContextUpgradeable.sol";
import "../utils/StringsUpgradeable.sol";
import "../utils/introspection/ERC165Upgradeable.sol";
import "../proxy/utils/Initializable.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControlUpgradeable, ERC165Upgradeable {
function __AccessControl_init() internal onlyInitializing {
}
function __AccessControl_init_unchained() internal onlyInitializing {
}
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlUpgradeable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
StringsUpgradeable.toHexString(account),
" is missing role ",
StringsUpgradeable.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/introspection/ERC165Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165Upgradeable.sol";
import "../../proxy/utils/Initializable.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165Upgradeable is Initializable, IERC165Upgradeable {
function __ERC165_init() internal onlyInitializing {
}
function __ERC165_init_unchained() internal onlyInitializing {
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165Upgradeable).interfaceId;
}
/**
* @dev This empty reserved space is put in place to allow future versions to add new
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[50] private __gap;
}
lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.0;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
lib/openzeppelin-contracts-upgradeable/contracts/interfaces/draft-IERC1822Upgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822ProxiableUpgradeable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}
contracts/sto/helpers/Errors.sol
/// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
/// @title Errors
/// @custom:security-contact tech@brickken.com
library Errors {
/// If a contract has been alredy initialized
error AlreadyInitialized();
/// Issuer `issuer` can't start a new Issuance Process if the Previous one has not been Finalized and Withdrawn
error IssuanceNotFinalized(address issuer);
/// Issuance start date has not been reached
error IssuanceNotStarted(address issuer);
/// Issuance soft cap has not been reached
error IssuanceNotSuccess(address issuer);
/// The Initialization of the Issuance Process sent by the Issuer `issuer` is not valid
error InitialValueWrong(address issuer);
/// The Patch of the Issuance value sent by the Admin is not valid
error PatchValueWrong(uint256 oldValue, uint256 newValue);
/// This transaction exceed the Max Supply of STO Token
error MaxSupplyExceeded();
/// This transaction exceed the Supply Cap of STO Token
error SupplyCapExceeded();
/// The issuance collected funds are not withdrawn yet
error IssuanceNotWithdrawn(address issuer);
/// The issuance process is not in rollback state
error IssuanceNotInRollback(uint256 index);
/// Fired when fees are over 100%
error FeeOverLimits(uint256 newFee);
/// The Issuer `issuer` tried to Finalize the Issuance Process before to End Date `endDate`
error IssuanceNotEnded(address issuer, uint256 endDate);
/// The Issuer `issuer` tried to Withdraw the Issuance Process was Withdrawn
error IssuanceWasWithdrawn(address issuer);
/// The Issuer `issuer` tried to Rollback the Issuance Process was Rollbacked
error IssuanceWasRollbacked(address issuer);
/// The User `user` tried to buy STO Token in the Issuance Process was ended in `endDate`
error IssuanceEnded(address user, uint256 endDate);
/// The User `user` tried to buy with ERC20 `token` is not WhiteListed in the Issuance Process
error TokenIsNotWhitelisted(address token, address user);
/// The User `user` tried to buy STO Token, and the Amount `amount` exceed the Maximal Ticket `maxTicket`
error AmountExceeded(address user, uint256 amount, uint256 maxTicket);
/// the User `user` tried to buy STO Token, and the Amount `amount` is under the Minimal Ticket `minTicket`
error InsufficientAmount(address user, uint256 amount, uint256 minTicket);
/// The value is negative
error NotNegativeValue(int256 value);
/// When something is wrong with Uniswap config
error WrongUniswapConfig();
/// Slippage control
error LessThanExpectedAmount(uint256 minExpected, uint256 amount);
/// The User already redeemed the tokens bought in previous investments
error TokensAlreadyReedemed(address user);
/// The User `user` has not enough balance `amount` in the ERC20 Token `token`
error InsufficientBalance(address user, address token, uint256 amount);
/// The User `user` tried to redeem the ERC20 Token Again! in the Issuance Process with Index `index`
error RedeemedAlready(address user, uint256 index);
/// The User `user` tried to be refunded with payment tokend Again! in the Issuance Process with Index `index`
error RefundedAlready(address user, uint256 index);
/// The User `user` is not Investor in the Issuance Process with Index `index`
error NotInvestor(address user, uint256 index);
/// The Max Amount of STO Token in the Issuance Process will be Raised
error HardCapRaised();
/// User `user`,don't have permission to reinitialize the contract
error UserIsNotAdmin(address user);
/// User is not Whitelisted, User `user`,don't have permission to transfer or call some functions
error UserIsNotWhitelisted(address user);
/// At least pair of arrays have a different length
error LengthsMismatch();
/// The premint Amount of STO Tokens in the Issuance Process exceeds the Max Amount of STO Tokens
error PremintGreaterThanMaxSupply();
/// The Address can't be zero address
error NotZeroAddress();
/// The Address is not a Contract
error NotContractAddress();
/// The Dividend Amount can't be zero
error DividendAmountIsZero();
/// The Wallet `claimer` is not Available to Claim Dividend
error NotAvailableToClaim(address claimer);
/// The User `claimer` can't claim
error NotAmountToClaim(address claimer);
///The User `user` try to claim an amount `amountToClaim` more than the amount available `amountAvailable`
error ExceedAmountAvailable(
address claimer,
uint256 amountAvailable,
uint256 amountToClaim
);
/// Confiscation Feature is Disabled
error ConfiscationDisabled();
// The token is not the payment token
error InvalidPaymentToken(address token);
// The deadline for the offchain price has expired
error ExpiredSignature(uint256 deadline, uint256 currentTimestamp);
// The retrieved address from ECDSA signature doesn't match allowed signed
error InvalidSigner(address retrievedAddress);
// Bad twap interval
error BadTwapIntervalValue(uint256 value);
// Null value not accepted
error NotZeroValue();
// Offchain amount exceeds available amount
error OffchainAmountExceedsAvailableAmount(
uint256 totalAmount,
uint256 availableAmount
);
// Not enough credits
error NotEnoughCredits();
/// Fired when fee amount to pay exceeds the available amount in paymentTokens
error FeeExceedsBalance(uint256 feeAmount, uint256 feeCoverageShortfall);
}
lib/openzeppelin-contracts/contracts/access/Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* By default, the owner account will be the one that deploys the contract. This
* can later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/
constructor() {
_transferOwnership(_msgSender());
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/StorageSlotUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/math/SignedMathUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMathUpgradeable {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}
contracts/sto/helpers/BeaconProxy.sol
// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
import { Proxy } from "@openzeppelin/contracts/proxy/Proxy.sol";
import { StorageSlot } from "@openzeppelin/contracts/utils/StorageSlot.sol";
import { IBeacon } from "@openzeppelin/contracts/proxy/beacon/IBeacon.sol";
import { ERC1967Upgrade } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
import { Address} from "@openzeppelin/contracts/utils/Address.sol";
import { Errors } from "./Errors.sol";
/**
* @dev This contract implements a proxy that gets the implementation address for each call from a {UpgradeableBeacon}.
*
* The beacon address is stored in storage slot `uint256(keccak256('eip1967.proxy.beacon')) - 1`, so that it doesn't
* conflict with the storage layout of the implementation behind the proxy.
*
* _Available since v3.4._
*/
/// @title BeaconProxy
/// @custom:security-contact tech@brickken.com
contract BeaconProxy is Proxy, ERC1967Upgrade {
/**
* @dev Initializes the proxy with `beacon`.
*
* If `data` is nonempty, it's used as data in a delegate call to the implementation returned by the beacon. This
* will typically be an encoded function call, and allows initializating the storage of the proxy like a Solidity
* constructor.
*
* Requirements:
*
* - `beacon` must be a contract with the interface {IBeacon}.
*/
constructor(address beacon, address admin, bytes memory data) payable {
if(
beacon == address(0) ||
admin == address(0)
) revert Errors.NotZeroAddress();
StorageSlot.getAddressSlot(_ADMIN_SLOT).value = admin; // Avoid emitting events
StorageSlot.getAddressSlot(_BEACON_SLOT).value = beacon; // Avoid emitting events
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(beacon).implementation(), data);
}
}
/**
* @dev Returns the current implementation address of the associated beacon.
*/
function _implementation() internal view override returns (address) {
if(_getImplementation() != address(0)) return _getImplementation();
return IBeacon(_getBeacon()).implementation();
}
/// Make sure that below functions don't clash with implementation function signatures
/**
* @dev Returns the current beacon address.
*/
function getImplementation() external view returns (address) {
return _implementation();
}
/**
* @dev Change the current admin.
*/
function changeProxyAdmin(address _newAdmin) external {
require(msg.sender == _getAdmin(), "BeaconProxy: only admin");
_changeAdmin(_newAdmin);
}
/**
* @dev Override beacon and set implementation manually, if set to non null value, beacon will be ignored.
*/
function changeImplementationOverrideBeacon(address newImplementation) external {
require(msg.sender == _getAdmin(), "BeaconProxy: only admin");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Renounce upgradeability forever, will set implementation to current beacon value and will prohibit from further upgrading it
*/
function renounceUpgradeability(address finalImplementation) external {
require(msg.sender == _getAdmin(), "BeaconProxy: only admin");
require(finalImplementation != address(0), "BeaconProxy: final implementation is null");
StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = finalImplementation;
_changeAdmin(address(0xdead));
}
}
contracts/sto/helpers/UniswapLibraries.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity <0.9.0;
/// @title Math library for computing sqrt prices from ticks and vice versa
/// @notice Computes sqrt price for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. Supports
/// prices between 2**-128 and 2**128
library TickMath {
error T();
error R();
/// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128
int24 internal constant MIN_TICK = -887272;
/// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128
int24 internal constant MAX_TICK = -MIN_TICK;
/// @dev The minimum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MIN_TICK)
uint160 internal constant MIN_SQRT_RATIO = 4295128739;
/// @dev The maximum value that can be returned from #getSqrtRatioAtTick. Equivalent to getSqrtRatioAtTick(MAX_TICK)
uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;
/// @notice Calculates sqrt(1.0001^tick) * 2^96
/// @dev Throws if |tick| > max tick
/// @param tick The input tick for the above formula
/// @return sqrtPriceX96 A Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)
/// at the given tick
function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {
unchecked {
uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));
if (absTick > uint256(int256(MAX_TICK))) revert T();
uint256 ratio = absTick & 0x1 != 0
? 0xfffcb933bd6fad37aa2d162d1a594001
: 0x100000000000000000000000000000000;
if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;
if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;
if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;
if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;
if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;
if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;
if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;
if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;
if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;
if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;
if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;
if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;
if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;
if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;
if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;
if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;
if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;
if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;
if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;
if (tick > 0) ratio = type(uint256).max / ratio;
// this divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.
// we then downcast because we know the result always fits within 160 bits due to our tick input constraint
// we round up in the division so getTickAtSqrtRatio of the output price is always consistent
sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));
}
}
/// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio
/// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may
/// ever return.
/// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96
/// @return tick The greatest tick for which the ratio is less than or equal to the input ratio
function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {
unchecked {
// second inequality must be < because the price can never reach the price at the max tick
if (!(sqrtPriceX96 >= MIN_SQRT_RATIO && sqrtPriceX96 < MAX_SQRT_RATIO)) revert R();
uint256 ratio = uint256(sqrtPriceX96) << 32;
uint256 r = ratio;
uint256 msb = 0;
assembly {
let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(5, gt(r, 0xFFFFFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(4, gt(r, 0xFFFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(3, gt(r, 0xFF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(2, gt(r, 0xF))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := shl(1, gt(r, 0x3))
msb := or(msb, f)
r := shr(f, r)
}
assembly {
let f := gt(r, 0x1)
msb := or(msb, f)
}
if (msb >= 128) r = ratio >> (msb - 127);
else r = ratio << (127 - msb);
int256 log_2 = (int256(msb) - 128) << 64;
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(63, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(62, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(61, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(60, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(59, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(58, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(57, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(56, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(55, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(54, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(53, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(52, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(51, f))
r := shr(f, r)
}
assembly {
r := shr(127, mul(r, r))
let f := shr(128, r)
log_2 := or(log_2, shl(50, f))
}
int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number
int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);
int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);
tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;
}
}
/// @dev Uniswap function to recover the price from the tick
function getQuoteAtTick(
int24 tick,
uint256 baseAmount,
address baseToken,
address quoteToken
) internal pure returns (uint256 quoteAmount) {
uint160 sqrtRatioX96 = TickMath.getSqrtRatioAtTick(tick);
// Calculate quoteAmount with better precision if it doesn't overflow when multiplied by itself
if (sqrtRatioX96 <= type(uint128).max) {
uint256 ratioX192 = uint256(sqrtRatioX96) * sqrtRatioX96;
quoteAmount = baseToken < quoteToken
? FullMath.mulDiv(ratioX192, baseAmount, 1 << 192)
: FullMath.mulDiv(1 << 192, baseAmount, ratioX192);
} else {
uint256 ratioX128 = FullMath.mulDiv(sqrtRatioX96, sqrtRatioX96, 1 << 64);
quoteAmount = baseToken < quoteToken
? FullMath.mulDiv(ratioX128, baseAmount, 1 << 128)
: FullMath.mulDiv(1 << 128, baseAmount, ratioX128);
}
}
}
/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
/// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
/// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
function mulDiv(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = a * b
// Compute the product mod 2**256 and mod 2**256 - 1
// then use the Chinese Remainder Theorem to reconstruct
// the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2**256 + prod0
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(a, b, not(0))
prod0 := mul(a, b)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division
if (prod1 == 0) {
require(denominator > 0);
assembly {
result := div(prod0, denominator)
}
return result;
}
// Make sure the result is less than 2**256.
// Also prevents denominator == 0
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0]
// Compute remainder using mulmod
uint256 remainder;
assembly {
remainder := mulmod(a, b, denominator)
}
// Subtract 256 bit number from 512 bit number
assembly {
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator
// Compute largest power of two divisor of denominator.
// Always >= 1.
uint256 twos = (0 - denominator) & denominator;
// Divide denominator by power of two
assembly {
denominator := div(denominator, twos)
}
// Divide [prod1 prod0] by the factors of two
assembly {
prod0 := div(prod0, twos)
}
// Shift in bits from prod1 into prod0. For this we need
// to flip `twos` such that it is 2**256 / twos.
// If twos is zero, then it becomes one
assembly {
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
// Invert denominator mod 2**256
// Now that denominator is an odd number, it has an inverse
// modulo 2**256 such that denominator * inv = 1 mod 2**256.
// Compute the inverse by starting with a seed that is correct
// correct for four bits. That is, denominator * inv = 1 mod 2**4
uint256 inv = (3 * denominator) ^ 2;
// Now use Newton-Raphson iteration to improve the precision.
// Thanks to Hensel's lifting lemma, this also works in modular
// arithmetic, doubling the correct bits in each step.
inv *= 2 - denominator * inv; // inverse mod 2**8
inv *= 2 - denominator * inv; // inverse mod 2**16
inv *= 2 - denominator * inv; // inverse mod 2**32
inv *= 2 - denominator * inv; // inverse mod 2**64
inv *= 2 - denominator * inv; // inverse mod 2**128
inv *= 2 - denominator * inv; // inverse mod 2**256
// Because the division is now exact we can divide by multiplying
// with the modular inverse of denominator. This will give us the
// correct result modulo 2**256. Since the precoditions guarantee
// that the outcome is less than 2**256, this is the final result.
// We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inv;
return result;
}
}
/// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
/// @param a The multiplicand
/// @param b The multiplier
/// @param denominator The divisor
/// @return result The 256-bit result
function mulDivRoundingUp(
uint256 a,
uint256 b,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
result = mulDiv(a, b, denominator);
if (mulmod(a, b, denominator) > 0) {
require(result < type(uint256).max);
result++;
}
}
}
}
lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.0;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```solidity
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._
* _Available since v4.9 for `string`, `bytes`._
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
/// @solidity memory-safe-assembly
assembly {
r.slot := store.slot
}
}
}
lib/openzeppelin-contracts-upgradeable/contracts/utils/StringsUpgradeable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/MathUpgradeable.sol";
import "./math/SignedMathUpgradeable.sol";
/**
* @dev String operations.
*/
library StringsUpgradeable {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = MathUpgradeable.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMathUpgradeable.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, MathUpgradeable.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.2;
import "../../utils/AddressUpgradeable.sol";
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
* @custom:oz-retyped-from bool
*/
uint8 private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint8 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a
* constructor.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
bool isTopLevelCall = !_initializing;
require(
(isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),
"Initializable: contract is already initialized"
);
_initialized = 1;
if (isTopLevelCall) {
_initializing = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: setting the version to 255 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint8 version) {
require(!_initializing && _initialized < version, "Initializable: contract is already initialized");
_initialized = version;
_initializing = true;
_;
_initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
require(_initializing, "Initializable: contract is not initializing");
_;
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
require(!_initializing, "Initializable: contract is initializing");
if (_initialized != type(uint8).max) {
_initialized = type(uint8).max;
emit Initialized(type(uint8).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint8) {
return _initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _initializing;
}
}
contracts/sto/interfaces/ChainlinkInterfaces.sol
// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
interface IChainlinkPriceFeed {
function decimals() external view returns (uint8);
function getRoundData(
uint80 id
)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestRoundData()
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
contracts/sto/helpers/PriceAndSwapManager.sol
// SPDX-License-Identifier: MIT
pragma solidity <0.9.0;
import { Roles } from "./Roles.sol";
import { Errors } from "./Errors.sol";
import { TickMath } from "./UniswapLibraries.sol";
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IChainlinkPriceFeed } from "../interfaces/ChainlinkInterfaces.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { IUniswapV3Pair, IUniswapV3Factory, IUniswapV3Router } from "../interfaces/UniswapInterfaces.sol";
import { IPriceAndSwapManager } from "../interfaces/IPriceAndSwapManager.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
/// @title PriceAndSwapManager: contract that handles logic for the STOEscrowUpgradeable contract. Due to contract size limit we had to hand off this into a separate contract.
/// It abstracts away price recovery and swap logic. It supports Uniswap v3 pools and Chainlink price feeds.
/// This is a stateless, non upgradeable contract that is deployed once for every chain and to which all escrows will need to point to.
/// If this needs to change, the factory has methods to change it accordingly to a newly deployed one.
/// @custom:security-contact tech@brickken.com
contract PriceAndSwapManager is IPriceAndSwapManager, Initializable {
using Math for uint256;
using SafeERC20 for IERC20Metadata;
address public stoFactory;
mapping(address caller => bool allowanceStatus) public allowedCaller;
// Only contracts allowed by the factory can call functions with this modifer
modifier onlyAllowed() {
if(!allowedCaller[msg.sender]) revert Errors.UserIsNotWhitelisted(msg.sender);
_;
}
// Only the factory contract can call functions with this modifer
modifier onlyFactory() {
if(msg.sender != stoFactory) revert Errors.UserIsNotAdmin(msg.sender);
_;
}
function initialize(address _factory) external initializer {
if(_factory == address(0)) revert Errors.NotZeroAddress();
stoFactory = _factory;
}
/// @inheritdoc IPriceAndSwapManager
function setAllowed(address toBeSet, bool status) external onlyFactory {
allowedCaller[toBeSet] = status;
}
/// @inheritdoc IPriceAndSwapManager
function getEstimationSTOToken(
address caller,
OfferingDetails calldata offeringDetails,
UserDetails calldata userDetails,
TokenUsedDetails calldata tokenUsedDetails,
EscrowDetails calldata escrowDetails
) external view returns (uint256 expectedAmount) {
uint256 actualAmount;
if (
(!escrowDetails.stoRelatedToken.hasRole(Roles.TOKEN_WHITELIST_ROLE, caller) && !escrowDetails.stoRelatedToken.whitelist_OLD_SLOT(caller)) ||
offeringDetails.issuanceIndex == 0 ||
offeringDetails.isEnded ||
!tokenUsedDetails.isTokenWhitelisted ||
offeringDetails.raisedAmount == offeringDetails.hardCap
) return(0);
if (address(tokenUsedDetails.tokenAddress) != address(escrowDetails.paymentToken)) {
uint256 priceInPaymentToken = getPriceInPaymentToken(
PoolDetails(
address(tokenUsedDetails.tokenAddress),
address(escrowDetails.paymentToken),
escrowDetails.router,
uint24(tokenUsedDetails.whitelistedTokenFeesOnSwap)
),
escrowDetails.twapInterval
);
uint256 amountOfPaymentTokens = tokenUsedDetails.amountOfTokens.mulDiv( // Amount of paymentTokens equivalent to the amount passed in
priceInPaymentToken,
10 ** IERC20Metadata(tokenUsedDetails.tokenAddress).decimals(),
Math.Rounding.Down
); ///Rounding Down
actualAmount = amountOfPaymentTokens;
} else {
actualAmount = tokenUsedDetails.amountOfTokens;
}
uint256 stoRelatedTokenScale = 10 ** escrowDetails.stoRelatedToken.decimals();
uint256 usdPriceOfPaymentToken = getUSDPriceOfPaymentToken(
escrowDetails.paymentTokenOracle,
escrowDetails.twapInterval
);
uint256 paymentTokenScale = 10 ** IERC20Metadata(escrowDetails.paymentToken).decimals();
uint256 usdValue = actualAmount.mulDiv(
usdPriceOfPaymentToken,
paymentTokenScale,
Math.Rounding.Down
);
if ( // alllow quantities less than minTicket only if what's left is minor than minTicket
((usdValue < offeringDetails.minTicket) &&
(offeringDetails.hardCap - offeringDetails.raisedAmount) >= offeringDetails.minTicket) ||
usdValue > offeringDetails.maxTicket // Disallow values for more than maxTicket
) return(0);
// If investor already invested previously, check that his total ticket doesn't exceed maxTicket
if(userDetails.isUserInvestor) {
uint256 totalValue = (userDetails.userAmountOfPaymentTokens + actualAmount).mulDiv(
usdPriceOfPaymentToken,
paymentTokenScale,
Math.Rounding.Down
);
if (totalValue > offeringDetails.maxTicket) return(0);
}
uint256 maxAmount;
if (usdValue + offeringDetails.raisedAmount > offeringDetails.hardCap)
{
// Raised amount can never be greater than hardCap
uint256 difference = offeringDetails.hardCap - offeringDetails.raisedAmount;
maxAmount = difference.mulDiv(
paymentTokenScale,
usdPriceOfPaymentToken,
Math.Rounding.Up);
}
if(maxAmount > 0) {
actualAmount = maxAmount;
}
expectedAmount = actualAmount
.mulDiv(
usdPriceOfPaymentToken,
paymentTokenScale,
Math.Rounding.Up
)
.mulDiv(
stoRelatedTokenScale,
offeringDetails.priceInUSD,
Math.Rounding.Down
);
}
/// @inheritdoc IPriceAndSwapManager
function getUSDPriceOfPaymentToken(
IChainlinkPriceFeed paymentTokenOracle,
uint256 twapInterval
) public view returns (uint256) {
// If the paymentTokenOracle is address(0) it returns unitari price as it means that
// the corresponding paymentToken must not be priced.
// This is expecially true for utility -> equity conversion where the price of the utility doesn't matter
// Returning an unitary price means assigning the same number to amount and value of X tokens.
if(address(paymentTokenOracle) == address(0)) {
return uint256(1e18);
}
(uint80 roundId, int256 price, , uint256 updatedAt, ) = paymentTokenOracle.latestRoundData();
int256 finalPrice = _getChainlinkTWAP(roundId, price, twapInterval, updatedAt, paymentTokenOracle);
if(finalPrice < 0) revert Errors.NotNegativeValue(finalPrice);
uint8 chainlinkDecimals = paymentTokenOracle.decimals();
uint8 base = 18;
if(chainlinkDecimals <= base) return uint256(finalPrice).mulDiv(10**(base-chainlinkDecimals), 1, Math.Rounding.Up);
else return uint256(finalPrice).mulDiv(1, 10**(chainlinkDecimals - base), Math.Rounding.Up);
}
/// @inheritdoc IPriceAndSwapManager
function getPriceInPaymentToken(
PoolDetails memory poolDetails,
uint256 twapInterval
) public view returns (uint256 price) {
if (poolDetails.tokenAddress == address(poolDetails.paymentToken)) return 10**IERC20Metadata(poolDetails.paymentToken).decimals();
IUniswapV3Pair pool = IUniswapV3Pair(
IUniswapV3Factory(
poolDetails.router.factory()
).getPool(
poolDetails.tokenAddress, // The order doesn't matter since Uniswap populates mappings in both directions
address(poolDetails.paymentToken),
uint24(poolDetails.fees)
)
);
if(address(pool) == address(0)) revert Errors.NotZeroAddress();
address poolToken0 = pool.token0();
address poolToken1 = pool.token1();
if (
poolToken0 == address(poolDetails.paymentToken) && poolToken1 == poolDetails.tokenAddress
) {
address oldToken = poolToken0;
poolToken0 = poolToken1;
poolToken1 = oldToken;
} else if(
!(poolToken0 == poolDetails.tokenAddress && poolToken1 == address(poolDetails.paymentToken))
) revert Errors.WrongUniswapConfig();
{
uint32[] memory secondsAgos = new uint32[](2);
secondsAgos[0] = uint32(twapInterval);
secondsAgos[1] = 0;
(int56[] memory tickCumulatives, ) = pool.observe(secondsAgos);
int56 tickCumulativesDelta = tickCumulatives[1] - tickCumulatives[0];
int24 tick = int24(tickCumulativesDelta / int56(int256(twapInterval)));
if (tickCumulativesDelta < 0 && (tickCumulativesDelta % int256(twapInterval) != 0)) {
tick--;
}
price = uint256(
TickMath.getQuoteAtTick(
tick,
10 ** IERC20Metadata(poolDetails.tokenAddress).decimals(),
poolDetails.tokenAddress,
address(poolDetails.paymentToken)
)
);
}
}
/// @inheritdoc IPriceAndSwapManager
function resetAllowances(
address oldAddress,
address newAddress,
address[] memory tokensERC20
) external onlyAllowed {
for (uint256 i = 0; i < tokensERC20.length;) {
IERC20Metadata _token = IERC20Metadata(
tokensERC20[i]
);
uint256 oldAllowance = _token.allowance(address(this), oldAddress);
if (oldAllowance > 0) {
_token.safeDecreaseAllowance(oldAddress, oldAllowance);
}
uint256 currentAllowance = _token.allowance(
address(this),
address(newAddress)
);
if (currentAllowance != 0) {
_token.safeIncreaseAllowance(
address(newAddress),
oldAllowance
);
}
unchecked {
++i;
}
}
}
/// @inheritdoc IPriceAndSwapManager
function swapTokensForPaymentTokens(
PoolDetails calldata poolDetails,
uint256 tokenAmount,
uint256 expectedAmount
) external onlyAllowed {
uint256 currentAllowance = IERC20Metadata(poolDetails.tokenAddress).allowance(address(this), address(poolDetails.router));
if(currentAllowance <= tokenAmount) {
IERC20Metadata(poolDetails.tokenAddress).safeIncreaseAllowance(address(poolDetails.router), tokenAmount - currentAllowance);
}
IUniswapV3Router.ExactInputSingleParams memory params = IUniswapV3Router.ExactInputSingleParams({
tokenIn: address(poolDetails.tokenAddress),
tokenOut: address(poolDetails.paymentToken),
fee: uint24(poolDetails.fees),
recipient: msg.sender,
amountIn: tokenAmount,
amountOutMinimum: expectedAmount,
sqrtPriceLimitX96: 0
});
poolDetails.router.exactInputSingle(params); // Uniswap reverts if outputAmount < expectedAmount with "Too little received"
}
/// Internal functions
/// @dev Calculate the TWAP of the retrieved Chainlink price
function _getChainlinkTWAP(
uint80 latestRoundId,
int256 latestPrice,
uint256 twapTimeInterval,
uint256 latestUpdate,
IChainlinkPriceFeed paymentTokenOracle
) internal view returns (int256) {
int256 priceSum = latestPrice;
uint256 priceCount = 1;
uint256 startTime = latestUpdate - twapTimeInterval;
while (latestRoundId > 0) {
try paymentTokenOracle.getRoundData(--latestRoundId) returns (
uint80,
int256 answer,
uint256,
uint256 updatedAt,
uint80
) {
if (updatedAt < startTime) {
break;
}
priceSum += answer;
priceCount++;
} catch {
break;
}
}
return priceSum / int256(priceCount);
}
}
lib/openzeppelin-contracts/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
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
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 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://consensys.net/diligence/blog/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} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
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");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
Compiler Settings
{"viaIR":false,"remappings":["ethereum-vault-connector/=lib/ethereum-vault-connector/src/","permit2/=lib/permit2/","ds-test/=lib/ethereum-vault-connector/lib/forge-std/lib/ds-test/src/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/","forge-std/=lib/forge-std/src/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","contracts/=contracts/","dto/escrow/=contracts/dto/escrow/","dto/factory/=contracts/dto/factory/","dto/token/=contracts/dto/token/","dto/helpers/=contracts/dto/helpers/","dto/interfaces/=contracts/dto/interfaces/","dto/mocks/=contracts/dto/mocks/","sto/escrow/=contracts/sto/escrow/","sto/factory/=contracts/sto/factory/","sto/token/=contracts/sto/token/","sto/helpers/=contracts/sto/helpers/","sto/interfaces/=contracts/sto/interfaces/","sto/mocks/=contracts/sto/mocks/","brickken/=contracts/brickken/","@ensdomains/=node_modules/@ensdomains/","eth-gas-reporter/=node_modules/eth-gas-reporter/","hardhat/=node_modules/hardhat/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/","openzeppelin/=lib/openzeppelin-contracts/contracts/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":100,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"none","appendCBOR":false},"libraries":{},"evmVersion":"prague"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_router","internalType":"address"},{"type":"address","name":"_priceAndSwapManager","internalType":"address"}]},{"type":"error","name":"ExpiredSignature","inputs":[{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"uint256","name":"currentTimestamp","internalType":"uint256"}]},{"type":"error","name":"InvalidSigner","inputs":[{"type":"address","name":"retrievedAddress","internalType":"address"}]},{"type":"error","name":"LengthsMismatch","inputs":[]},{"type":"error","name":"NotZeroAddress","inputs":[]},{"type":"error","name":"PremintGreaterThanMaxSupply","inputs":[]},{"type":"error","name":"SupplyCapExceeded","inputs":[]},{"type":"error","name":"UserIsNotAdmin","inputs":[{"type":"address","name":"user","internalType":"address"}]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ChargeFee","inputs":[{"type":"address","name":"issuer","internalType":"address","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":false},{"type":"uint256","name":"amount","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"type":"uint8","name":"version","internalType":"uint8","indexed":false}],"anonymous":false},{"type":"event","name":"NewTokenization","inputs":[{"type":"uint256","name":"id","internalType":"uint256","indexed":true},{"type":"address","name":"token","internalType":"address","indexed":true},{"type":"address","name":"escrow","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Paused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"previousAdminRole","internalType":"bytes32","indexed":true},{"type":"bytes32","name":"newAdminRole","internalType":"bytes32","indexed":true}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32","indexed":true},{"type":"address","name":"account","internalType":"address","indexed":true},{"type":"address","name":"sender","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"Unpaused","inputs":[{"type":"address","name":"account","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"DEFAULT_ADMIN_ROLE","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"HASH_NAME","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"HASH_VERSION","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"brickkenVault","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"changeConfig","inputs":[{"type":"address","name":"vault","internalType":"address"},{"type":"address","name":"beaconToken","internalType":"address"},{"type":"address","name":"beaconEscrow","internalType":"address"},{"type":"address[]","name":"allowedEscrows","internalType":"address[]"},{"type":"bool[]","name":"allowedEscrowsStatuses","internalType":"bool[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountToPay","internalType":"uint256"},{"type":"address","name":"signer","internalType":"address"}],"name":"getFees","inputs":[{"type":"tuple","name":"offchainReport","internalType":"struct ISTOFactoryUpgradeable.OffchainReport","components":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"tokenAmount","internalType":"uint256"},{"type":"address","name":"spender","internalType":"address"},{"type":"address","name":"issuer","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"bytes","name":"signature","internalType":"bytes"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getImplementation","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getRoleAdmin","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getRoleMember","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRoleMemberCount","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"grantRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"hasRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"idSTOs","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"initialize","inputs":[{"type":"address","name":"beaconToken","internalType":"address"},{"type":"address","name":"beaconEscrow","internalType":"address"},{"type":"address","name":"vault","internalType":"address"},{"type":"address","name":"admin","internalType":"address"},{"type":"address","name":"offchainSigner","internalType":"address"},{"type":"uint8","name":"version","internalType":"uint8"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"newTokenization","inputs":[{"type":"tuple","name":"config","internalType":"struct ISTOFactoryUpgradeable.TokenizationConfig","components":[{"type":"string","name":"url","internalType":"string"},{"type":"string","name":"name","internalType":"string"},{"type":"string","name":"symbol","internalType":"string"},{"type":"uint224","name":"supplyCap","internalType":"uint224"},{"type":"address","name":"paymentToken","internalType":"address"},{"type":"address","name":"paymentTokenOracle","internalType":"address"},{"type":"bool","name":"paymentTokenOracleUnused","internalType":"bool"},{"type":"uint256[]","name":"preMints","internalType":"uint256[]"},{"type":"address[]","name":"initialHolders","internalType":"address[]"}]},{"type":"tuple","name":"offchainReport","internalType":"struct ISTOFactoryUpgradeable.OffchainReport","components":[{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"tokenAmount","internalType":"uint256"},{"type":"address","name":"spender","internalType":"address"},{"type":"address","name":"issuer","internalType":"address"},{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"uint256","name":"nonce","internalType":"uint256"},{"type":"bytes","name":"signature","internalType":"bytes"}]},{"type":"tuple","name":"permit","internalType":"struct ISTOFactoryUpgradeable.PermitStruct","components":[{"type":"uint256","name":"deadline","internalType":"uint256"},{"type":"address","name":"signer","internalType":"address"},{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint8","name":"v","internalType":"uint8"},{"type":"bytes32","name":"r","internalType":"bytes32"},{"type":"bytes32","name":"s","internalType":"bytes32"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"nonces","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"pauseFactory","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"paused","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"priceAndSwapManager","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"proxiableUUID","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"revokeRole","inputs":[{"type":"bytes32","name":"role","internalType":"bytes32"},{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"router","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"stoBeaconEscrow","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"stoBeaconToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"escrowAddress","internalType":"address"}],"name":"stoEscrows","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"tokenAddress","internalType":"address"}],"name":"stoTokens","inputs":[{"type":"uint256","name":"id","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"supportsInterface","inputs":[{"type":"bytes4","name":"interfaceId","internalType":"bytes4"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"unpauseFactory","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]}]
Contract Creation Code
0x61010060405230608052348015610014575f5ffd5b50604051613fb8380380613fb88339810160408190526100339161015b565b81816001600160a01b03821661005c576040516366385fa360e01b815260040160405180910390fd5b5f60c0526001600160a01b0382811660e052811660a05261007b610084565b5050505061018c565b5f54610100900460ff16156100ef5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b5f5460ff9081161461013e575f805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b0381168114610156575f5ffd5b919050565b5f5f6040838503121561016c575f5ffd5b61017583610140565b915061018360208401610140565b90509250929050565b60805160a05160c05160e051613dc46101f45f395f818161068501526117bc01525f50505f818161042901528181610a4a0152818161184c015261192d01525f8181610788015281816107c80152818161084f0152818161088f01526109060152613dc45ff3fe6080604052600436106101b5575f3560e01c8063836b6511116100ea578063a290f20f1161008e578063a290f20f14610592578063aaf10f42146105b1578063af570608146105c5578063b6a33a38146105e4578063ca15c873146105f8578063d547741f14610617578063f2fde38b14610636578063f3d02cfd14610655578063f887ea4014610674575f5ffd5b8063836b65111461049f5780638da5cb5b146104b55780639010d07c146104d257806391d14854146104f15780639350d6f91461051057806395c4b6941461052f57806397ebad101461056b578063a217fddf1461057f575f5ffd5b80634f1ef2861161015c5780634f1ef2861461034e57806352d1902d14610361578063539a99a2146103755780635b30e378146103945780635c975abb146103ed578063715018a6146104045780637950a1f1146104185780637bfc417d1461044b5780637ecebe001461046a575f5ffd5b806301ffc9a7146101b9578063144aca35146101ed578063248a9ca31461022f57806325c522711461026c5780632f2ff15d146102ba57806336568abe146102db5780633659cfe6146102fa57806349f4f6a114610319575b5f5ffd5b3480156101c4575f5ffd5b506101d86101d3366004612940565b6106a7565b60405190151581526020015b60405180910390f35b3480156101f8575f5ffd5b50610222610207366004612967565b6101026020525f90815260409020546001600160a01b031681565b6040516101e4919061297e565b34801561023a575f5ffd5b5061025e610249366004612967565b5f90815261015f602052604090206001015490565b6040519081526020016101e4565b348015610277575f5ffd5b506040805180820190915260038152620312e360ec1b60209091015261025e7fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b381565b3480156102c5575f5ffd5b506102d96102d43660046129a8565b6106d1565b005b3480156102e6575f5ffd5b506102d96102f53660046129a8565b6106fb565b348015610305575f5ffd5b506102d96103143660046129d2565b61077e565b348015610324575f5ffd5b50610222610333366004612967565b6101036020525f90815260409020546001600160a01b031681565b6102d961035c366004612ab0565b610845565b34801561036c575f5ffd5b5061025e6108fa565b348015610380575f5ffd5b5060fe54610222906001600160a01b031681565b34801561039f575f5ffd5b5060408051808201909152600e81526d13d99998da185a5b94995c1bdc9d60921b60209091015261025e7fbab090260d0616f3025414422730bc27dc7b2a2f888694527569a75de342aecb81565b3480156103f8575f5ffd5b5060655460ff166101d8565b34801561040f575f5ffd5b506102d96109a6565b348015610423575f5ffd5b506102227f000000000000000000000000000000000000000000000000000000000000000081565b348015610456575f5ffd5b506102d9610465366004612b3a565b6109b9565b348015610475575f5ffd5b5061025e6104843660046129d2565b6001600160a01b03165f908152610105602052604090205490565b3480156104aa575f5ffd5b5061025e6101015481565b3480156104c0575f5ffd5b506033546001600160a01b0316610222565b3480156104dd575f5ffd5b506102226104ec366004612bd8565b610b37565b3480156104fc575f5ffd5b506101d861050b3660046129a8565b610b56565b34801561051b575f5ffd5b5060fd54610222906001600160a01b031681565b34801561053a575f5ffd5b5061054e610549366004612c0e565b610b81565b604080519283526001600160a01b039091166020830152016101e4565b348015610576575f5ffd5b506102d9610ba0565b34801561058a575f5ffd5b5061025e5f81565b34801561059d575f5ffd5b506102d96105ac366004612c4f565b610bde565b3480156105bc575f5ffd5b50610222610e0a565b3480156105d0575f5ffd5b5060fc54610222906001600160a01b031681565b3480156105ef575f5ffd5b506102d9610e18565b348015610603575f5ffd5b5061025e610612366004612967565b610e56565b348015610622575f5ffd5b506102d96106313660046129a8565b610e6d565b348015610641575f5ffd5b506102d96106503660046129d2565b610e92565b348015610660575f5ffd5b506102d961066f366004612cbf565b610f08565b34801561067f575f5ffd5b506102227f000000000000000000000000000000000000000000000000000000000000000081565b5f6001600160e01b03198216635a05180f60e01b14806106cb57506106cb82611090565b92915050565b5f82815261015f60205260409020600101546106ec816110c4565b6106f683836110ce565b505050565b6001600160a01b03811633146107705760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61077a82826110f0565b5050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630036107c65760405162461bcd60e51b815260040161076790612d38565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166107f8611112565b6001600160a01b03161461081e5760405162461bcd60e51b815260040161076790612d84565b6108278161112d565b604080515f8082526020820190925261084291839190611137565b50565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016300361088d5760405162461bcd60e51b815260040161076790612d38565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166108bf611112565b6001600160a01b0316146108e55760405162461bcd60e51b815260040161076790612d84565b6108ee8261112d565b61077a82826001611137565b5f306001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146109945760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610767565b505f516020613d7d5f395f51905f5290565b6109ae6112a1565b6109b75f6112fb565b565b5f6109c3816110c4565b838281146109e45760405163586cb9e160e01b815260040160405180910390fd5b6109ef89898961134c565b5f5b81811015610b2b575f878783818110610a0c57610a0c612dd0565b9050602002016020810190610a2191906129d2565b6001600160a01b031603610a48576040516366385fa360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634697f05d888884818110610a8957610a89612dd0565b9050602002016020810190610a9e91906129d2565b878785818110610ab057610ab0612dd0565b9050602002016020810190610ac59190612dfc565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152151560248201526044015f604051808303815f87803b158015610b0a575f5ffd5b505af1158015610b1c573d5f5f3e3d5ffd5b505050508060010190506109f1565b50505050505050505050565b5f82815261019160205260408120610b4f90836113d8565b9392505050565b5f91825261015f602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f80610b94610b8f84612e17565b6113e3565b60209093013593915050565b610ba8611441565b604051602001610bb790612eaa565b60405160208183030381529060405280519060200120610bd6816110c4565b61084261148a565b5f548190610100900460ff16158015610bfd57505f5460ff8083169116105b610c605760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610767565b5f805461ffff191660ff831617610100179055610c7b6114d6565b610c836114fc565b6001600160a01b038416610caa576040516366385fa360e01b815260040160405180910390fd5b610cb35f610e56565b15801590610cc85750610cc65f33610b56565b155b15610ce85733604051635486d5fd60e11b8152600401610767919061297e565b610cf15f610e56565b5f03610d5d57610d015f856110ce565b610d2f604051602001610d1390612eaa565b60405160208183030381529060405280519060200120856110ce565b610d5d604051602001610d4190612ed7565b60405160208183030381529060405280519060200120846110ce565b6001600160a01b038516610d84576040516366385fa360e01b815260040160405180910390fd5b60fc80546001600160a01b038781166001600160a01b03199283161790925560fd80548a841690831617905560fe8054928916929091169190911790555f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f610e13611112565b905090565b610e20611514565b604051602001610e2f90612eaa565b60405160208183030381529060405280519060200120610e4e816110c4565b61084261155a565b5f818152610191602052604081206106cb90611597565b5f82815261015f6020526040902060010154610e88816110c4565b6106f683836110f0565b610e9a6112a1565b6001600160a01b038116610eff5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610767565b610842816112fb565b610f10611514565b5f80610f27858585610f228580610b37565b6115a0565b604051634c1d96ab60e11b815291935091506001600160a01b0383169063983b2d5690610f5890849060040161297e565b5f604051808303815f87803b158015610f6f575f5ffd5b505af1158015610f81573d5f5f3e3d5ffd5b50505050816001600160a01b03166336568abe604051602001610fcf90602080825260179082015276544f4b454e5f4d494e5445525f41444d494e5f524f4c4560481b604082015260600190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b16825260048201523060248201526044015f604051808303815f87803b15801561101e575f5ffd5b505af1158015611030573d5f5f3e3d5ffd5b5050610101545f81815261010360209081526040808320546101029092528083205490516001600160a01b039283169650911693507ff3891eaa15d438132be54582fa326e471227aacade9ebed32006b0ba9d63254c9190a45050505050565b5f6001600160e01b03198216637965db0b60e01b14806106cb57506301ffc9a760e01b6001600160e01b03198316146106cb565b61084281336119c0565b6110d88282611a19565b5f828152610191602052604090206106f69082611a9f565b6110fa8282611ab3565b5f828152610191602052604090206106f69082611b1a565b5f516020613d7d5f395f51905f52546001600160a01b031690565b5f61077a816110c4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561116a576106f683611b2e565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111c4575060408051601f3d908101601f191682019092526111c191810190612f0e565b60015b6112275760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610767565b5f516020613d7d5f395f51905f5281146112955760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610767565b506106f6838383611bc9565b6033546001600160a01b031633146109b75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610767565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b038316158061136957506001600160a01b038216155b8061137b57506001600160a01b038116155b15611399576040516366385fa360e01b815260040160405180910390fd5b60fc80546001600160a01b039485166001600160a01b03199182161790915560fd80549385169382169390931790925560fe8054919093169116179055565b5f610b4f8383611bf3565b5f6113ed82611c19565b905061141d60405160200161140190612ed7565b6040516020818303038152906040528051906020012082610b56565b61143c578060405163bf18af4360e01b8152600401610767919061297e565b919050565b60655460ff166109b75760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610767565b611492611441565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516114cc919061297e565b60405180910390a1565b5f54610100900460ff166109b75760405162461bcd60e51b815260040161076790612f25565b611504611d0f565b61150c611d3d565b6109b76114d6565b60655460ff16156109b75760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610767565b611562611514565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114bf3390565b5f6106cb825490565b5f5f6115ac8585611d6b565b5f6115ba60e0880188612f70565b91508190506115cd610100890189612f70565b9050146115ed5760405163586cb9e160e01b815260040160405180910390fd5b5f805b828110156116315761160560e08a018a612f70565b8281811061161557611615612dd0565b90506020020135826116279190612fc9565b91506001016115f0565b506116426080890160608a01612ff2565b6001600160e01b03161580159061167057506116646080890160608a01612ff2565b6001600160e01b031681115b1561168e57604051637526372f60e01b815260040160405180910390fd5b6001600160e01b038111156116b657604051637ac7b99d60e11b815260040160405180910390fd5b6101015f81546116c59061300b565b909155505060fd546001600160a01b0316905083876116ea6080890160608a016129d2565b8660026040516024016117009493929190613146565b60408051601f198184030181529181526020820180516001600160e01b031663585873f560e11b1790525161173490612933565b611740939291906132d7565b604051809103905ff080158015611759573d5f5f3e3d5ffd5b5061010180545f908152610102602052604080822080546001600160a01b0319166001600160a01b0395861617905560fe5492548252902054908216918591166117a96080890160608a016129d2565b866117ba60a08c0160808d016129d2565b7f00000000000000000000000000000000000000000000000000000000000000006117eb60c08e0160a08f016129d2565b8d60c00160208101906117fe9190612dfc565b60fc546040516001600160a01b03988916602482015296881660448801529487166064870152928616608486015290851660a4850152841660c4840152151560e483015282166101048201527f000000000000000000000000000000000000000000000000000000000000000090911661012482015260026101448201526101640160408051601f198184030181529181526020820180516001600160e01b031663103fb0bb60e21b179052516118b490612933565b6118c0939291906132d7565b604051809103905ff0801580156118d9573d5f5f3e3d5ffd5b5061010180545f908152610103602052604080822080546001600160a01b0319166001600160a01b0395861617905591548152819020549051634697f05d60e01b81529082166004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000090911690634697f05d906044015f604051808303815f87803b158015611970575f5ffd5b505af1158015611982573d5f5f3e3d5ffd5b5050610101545f9081526101026020908152604080832054610103909252909120546001600160a01b03918216955016925050505b94509492505050565b6119ca8282610b56565b61077a576119d781611f12565b6119e2836020611f24565b6040516020016119f3929190613319565b60408051601f198184030181529082905262461bcd60e51b825261076791600401613368565b611a238282610b56565b61077a575f82815261015f602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611a5b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f610b4f836001600160a01b0384166120b9565b611abd8282610b56565b1561077a575f82815261015f602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f610b4f836001600160a01b038416612105565b6001600160a01b0381163b611b9b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610767565b5f516020613d7d5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b611bd2836121e8565b5f82511180611bde5750805b156106f657611bed8383612227565b50505050565b5f825f018281548110611c0857611c08612dd0565b905f5260205f200154905092915050565b60808101515f9042811015611c4a57604051636dd0bf4d60e11b815260048101829052426024820152604401610767565b5f7fac220aa699471afa03226e7e5c75686e50f65febb8df455cb4ff126c688be28d845f0151856020015186604001518760600151868960a00151604051602001611cd497969594939291909687526001600160a01b03958616602088015260408701949094529184166060860152909216608084015260a083019190915260c082015260e00190565b6040516020818303038152906040528051906020012090505f611cf68261224c565b9050611d06818660c0015161234a565b95945050505050565b5f54610100900460ff16611d355760405162461bcd60e51b815260040161076790612f25565b6109b761236c565b5f54610100900460ff16611d635760405162461bcd60e51b815260040161076790612f25565b6109b761239b565b5f5f611d7684610b81565b91509150611da1816001600160a01b03165f9081526101056020526040902080546001810190915590565b505f611db060208601866129d2565b90508215611f0b57833515611e8c576001600160a01b03811663d505accf611dde60408701602088016129d2565b611dee60608801604089016129d2565b60608801358835611e0560a08b0160808c0161337a565b6040516001600160e01b031960e088901b1681526001600160a01b0395861660048201529490931660248501526044840191909152606483015260ff16608482015260a087013560a482015260c087013560c482015260e4015f604051808303815f87803b158015611e75575f5ffd5b505af1158015611e87573d5f5f3e3d5ffd5b505050505b611eb281611ea060608801604089016129d2565b60fc546001600160a01b0316866123cd565b611ec260608601604087016129d2565b604080516001600160a01b0384811682526020820187905292909216917fc0d39cf3434f9dede81e427dbbccd901073df1b746711cb6cb7db1b27ddd6927910160405180910390a25b5050505050565b60606106cb6001600160a01b03831660145b60605f611f32836002613393565b611f3d906002612fc9565b6001600160401b03811115611f5457611f546129eb565b6040519080825280601f01601f191660200182016040528015611f7e576020820181803683370190505b509050600360fc1b815f81518110611f9857611f98612dd0565b60200101906001600160f81b03191690815f1a905350600f60fb1b81600181518110611fc657611fc6612dd0565b60200101906001600160f81b03191690815f1a9053505f611fe8846002613393565b611ff3906001612fc9565b90505b600181111561206a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061202757612027612dd0565b1a60f81b82828151811061203d5761203d612dd0565b60200101906001600160f81b03191690815f1a90535060049490941c93612063816133aa565b9050611ff6565b508315610b4f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610767565b5f8181526001830160205260408120546120fe57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106cb565b505f6106cb565b5f81815260018301602052604081205480156121df575f6121276001836133bf565b85549091505f9061213a906001906133bf565b9050818114612199575f865f01828154811061215857612158612dd0565b905f5260205f200154905080875f01848154811061217857612178612dd0565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806121aa576121aa6133d2565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506106cb565b5f9150506106cb565b6121f181611b2e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b4f8383604051806060016040528060278152602001613d9d60279139612427565b5f6106cb61232a604080518082018252600e81526d13d99998da185a5b94995c1bdc9d60921b6020918201528151808301835260038152620312e360ec1b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527fbab090260d0616f3025414422730bc27dc7b2a2f888694527569a75de342aecb818401527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b360608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f612357858561249b565b91509150612364816124dd565b509392505050565b5f54610100900460ff166123925760405162461bcd60e51b815260040161076790612f25565b6109b7336112fb565b5f54610100900460ff166123c15760405162461bcd60e51b815260040161076790612f25565b6065805460ff19169055565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611bed908590612621565b60605f5f856001600160a01b03168560405161244391906133e6565b5f60405180830381855af49150503d805f811461247b576040519150601f19603f3d011682016040523d82523d5f602084013e612480565b606091505b5091509150612491868383876126f4565b9695505050505050565b5f5f82516041036124cf576020830151604084015160608501515f1a6124c387828585612774565b945094505050506124d6565b505f905060025b9250929050565b5f8160048111156124f0576124f06133f1565b036124f85750565b600181600481111561250c5761250c6133f1565b036125545760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610767565b6002816004811115612568576125686133f1565b036125b55760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610767565b60038160048111156125c9576125c96133f1565b036108425760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610767565b5f612675826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166128249092919063ffffffff16565b905080515f14806126955750808060200190518101906126959190613405565b6106f65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610767565b606083156127625782515f0361275b576001600160a01b0385163b61275b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610767565b508161276c565b61276c8383612832565b949350505050565b5f806fa2a8918ca85bafe22016d0b997e4df60600160ff1b0383111561279f57505f905060036119b7565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156127f0573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116612818575f600192509250506119b7565b965f9650945050505050565b606061276c84845f8561285c565b8151156128425781518083602001fd5b8060405162461bcd60e51b81526004016107679190613368565b6060824710156128bd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610767565b5f5f866001600160a01b031685876040516128d891906133e6565b5f6040518083038185875af1925050503d805f8114612912576040519150601f19603f3d011682016040523d82523d5f602084013e612917565b606091505b5091509150612928878383876126f4565b979650505050505050565b61095c8061342183390190565b5f60208284031215612950575f5ffd5b81356001600160e01b031981168114610b4f575f5ffd5b5f60208284031215612977575f5ffd5b5035919050565b6001600160a01b0391909116815260200190565b80356001600160a01b038116811461143c575f5ffd5b5f5f604083850312156129b9575f5ffd5b823591506129c960208401612992565b90509250929050565b5f602082840312156129e2575f5ffd5b610b4f82612992565b634e487b7160e01b5f52604160045260245ffd5b60405160e081016001600160401b0381118282101715612a2157612a216129eb565b60405290565b5f82601f830112612a36575f5ffd5b81356001600160401b03811115612a4f57612a4f6129eb565b604051601f8201601f19908116603f011681016001600160401b0381118282101715612a7d57612a7d6129eb565b604052818152838201602001851015612a94575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f60408385031215612ac1575f5ffd5b612aca83612992565b915060208301356001600160401b03811115612ae4575f5ffd5b612af085828601612a27565b9150509250929050565b5f5f83601f840112612b0a575f5ffd5b5081356001600160401b03811115612b20575f5ffd5b6020830191508360208260051b85010111156124d6575f5ffd5b5f5f5f5f5f5f5f60a0888a031215612b50575f5ffd5b612b5988612992565b9650612b6760208901612992565b9550612b7560408901612992565b945060608801356001600160401b03811115612b8f575f5ffd5b612b9b8a828b01612afa565b90955093505060808801356001600160401b03811115612bb9575f5ffd5b612bc58a828b01612afa565b989b979a50959850939692959293505050565b5f5f60408385031215612be9575f5ffd5b50508035926020909101359150565b5f60e08284031215612c08575f5ffd5b50919050565b5f60208284031215612c1e575f5ffd5b81356001600160401b03811115612c33575f5ffd5b61276c84828501612bf8565b803560ff8116811461143c575f5ffd5b5f5f5f5f5f5f60c08789031215612c64575f5ffd5b612c6d87612992565b9550612c7b60208801612992565b9450612c8960408801612992565b9350612c9760608801612992565b9250612ca560808801612992565b9150612cb360a08801612c3f565b90509295509295509295565b5f5f5f6101208486031215612cd2575f5ffd5b83356001600160401b03811115612ce7575f5ffd5b84016101208187031215612cf9575f5ffd5b925060208401356001600160401b03811115612d13575f5ffd5b612d1f86828701612bf8565b925050612d2f8560408601612bf8565b90509250925092565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b8015158114610842575f5ffd5b803561143c81612de4565b5f60208284031215612e0c575f5ffd5b8135610b4f81612de4565b5f60e08236031215612e27575f5ffd5b612e2f6129ff565b612e3883612992565b815260208381013590820152612e5060408401612992565b6040820152612e6160608401612992565b60608201526080838101359082015260a0808401359082015260c08301356001600160401b03811115612e92575f5ffd5b612e9e36828601612a27565b60c08301525092915050565b602080825260139082015272464143544f52595f5041555345525f524f4c4560681b604082015260600190565b6020808252601e908201527f464143544f52595f4f4646434841494e5f5245504f525445525f524f4c450000604082015260600190565b5f60208284031215612f1e575f5ffd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f5f8335601e19843603018112612f85575f5ffd5b8301803591506001600160401b03821115612f9e575f5ffd5b6020019150600581901b36038213156124d6575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156106cb576106cb612fb5565b80356001600160e01b038116811461143c575f5ffd5b5f60208284031215613002575f5ffd5b610b4f82612fdc565b5f6001820161301c5761301c612fb5565b5060010190565b5f5f8335601e19843603018112613038575f5ffd5b83016020810192503590506001600160401b03811115613056575f5ffd5b8036038213156124d6575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f5f8335601e198436030181126130a1575f5ffd5b83016020810192503590506001600160401b038111156130bf575f5ffd5b8060051b36038213156124d6575f5ffd5b8183525f6001600160fb1b038311156130e7575f5ffd5b8260051b80836020870137939093016020019392505050565b8183526020830192505f815f5b8481101561313c576001600160a01b0361312683612992565b168652602095860195919091019060010161310d565b5093949350505050565b608081525f6131558687613023565b610120608085015261316c6101a085018284613064565b91505061317c6020880188613023565b848303607f190160a0860152613193838284613064565b925050506131a46040880188613023565b848303607f190160c08601526131bb838284613064565b925050506131cb60608801612fdc565b6001600160e01b031660e08401526131e560808801612992565b6001600160a01b031661010084015261320060a08801612992565b6001600160a01b031661012084015261321b60c08801612df1565b151561014084015261323060e088018861308c565b848303607f19016101608601526132488382846130d0565b9250505061325a61010088018861308c565b848303607f1901610180860152613272838284613100565b935050505061328c60208301866001600160a01b03169052565b6001600160a01b038416604083015260ff83166060830152611d06565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b038481168252831660208201526060604082018190525f90611d06908301846132a9565b5f81518060208401855e5f93019283525090919050565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81525f6133446017830185613302565b7001034b99036b4b9b9b4b733903937b6329607d1b8152611d066011820185613302565b602081525f610b4f60208301846132a9565b5f6020828403121561338a575f5ffd5b610b4f82612c3f565b80820281158282048414176106cb576106cb612fb5565b5f816133b8576133b8612fb5565b505f190190565b818103818111156106cb576106cb612fb5565b634e487b7160e01b5f52603160045260245ffd5b5f610b4f8284613302565b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215613415575f5ffd5b8151610b4f81612de456fe608060405260405161095c38038061095c833981016040819052610022916102d0565b6001600160a01b038316158061003f57506001600160a01b038216155b1561005d576040516366385fa360e01b815260040160405180910390fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610380546001600160a01b0319166001600160a01b038416179055827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b039290921691909117905580511561014957610147836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561011d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014191906103a1565b82610151565b505b505050610405565b606061017683836040518060600160405280602781526020016109356027913961017d565b9392505050565b60605f5f856001600160a01b03168560405161019991906103ba565b5f60405180830381855af49150503d805f81146101d1576040519150601f19603f3d011682016040523d82523d5f602084013e6101d6565b606091505b5090925090506101e8868383876101f2565b9695505050505050565b606083156102655782515f0361025e576001600160a01b0385163b61025e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161026f565b61026f8383610277565b949350505050565b8151156102875781518083602001fd5b8060405162461bcd60e51b815260040161025591906103d0565b80516001600160a01b03811681146102b7575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f606084860312156102e2575f5ffd5b6102eb846102a1565b92506102f9602085016102a1565b60408501519092506001600160401b03811115610314575f5ffd5b8401601f81018613610324575f5ffd5b80516001600160401b0381111561033d5761033d6102bc565b604051601f8201601f19908116603f011681016001600160401b038111828210171561036b5761036b6102bc565b604052818152828201602001881015610382575f5ffd5b8160208401602083015e5f602083830101528093505050509250925092565b5f602082840312156103b1575f5ffd5b610176826102a1565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b610523806104125f395ff3fe608060405260043610610042575f3560e01c8063611726df146100595780639f712f2f14610078578063aaf10f4214610097578063bebc0fbf146100c757610051565b366100515761004f6100e6565b005b61004f6100e6565b348015610064575f5ffd5b5061004f610073366004610494565b6100f8565b348015610083575f5ffd5b5061004f610092366004610494565b6101d6565b3480156100a2575f5ffd5b506100ab610217565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d2575f5ffd5b5061004f6100e1366004610494565b610225565b6100f66100f161028e565b610315565b565b610100610333565b6001600160a01b0316336001600160a01b0316146101395760405162461bcd60e51b8152600401610130906104b6565b60405180910390fd5b6001600160a01b0381166101a15760405162461bcd60e51b815260206004820152602960248201527f426561636f6e50726f78793a2066696e616c20696d706c656d656e746174696f6044820152681b881a5cc81b9d5b1b60ba1b6064820152608401610130565b5f5160206105035f395f51905f5280546001600160a01b0319166001600160a01b0383161790556101d361dead610365565b50565b6101de610333565b6001600160a01b0316336001600160a01b03161461020e5760405162461bcd60e51b8152600401610130906104b6565b6101d381610365565b5f61022061028e565b905090565b61022d610333565b6001600160a01b0316336001600160a01b03161461025d5760405162461bcd60e51b8152600401610130906104b6565b805f5160206105035f395f51905f525b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f806102986103b9565b6001600160a01b0316146102ae576102206103b9565b6102b66103cd565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f1573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022091906104e7565b365f5f375f5f365f845af43d5f5f3e80801561032f573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61038e610333565b604080516001600160a01b03928316815291841660208301520160405180910390a16101d3816103f4565b5f5f5160206105035f395f51905f52610356565b5f7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50610356565b6001600160a01b0381166104595760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610130565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610361026d565b6001600160a01b03811681146101d3575f5ffd5b5f602082840312156104a4575f5ffd5b81356104af81610480565b9392505050565b6020808252601790820152762132b0b1b7b7283937bc3c9d1037b7363c9030b236b4b760491b604082015260600190565b5f602082840312156104f7575f5ffd5b81516104af8161048056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564000000000000000000000000f02bd811d74e5b3e1866bd19e1b8451d48f58bd60000000000000000000000000000000000000000000000000000000000000000
Deployed ByteCode
0x6080604052600436106101b5575f3560e01c8063836b6511116100ea578063a290f20f1161008e578063a290f20f14610592578063aaf10f42146105b1578063af570608146105c5578063b6a33a38146105e4578063ca15c873146105f8578063d547741f14610617578063f2fde38b14610636578063f3d02cfd14610655578063f887ea4014610674575f5ffd5b8063836b65111461049f5780638da5cb5b146104b55780639010d07c146104d257806391d14854146104f15780639350d6f91461051057806395c4b6941461052f57806397ebad101461056b578063a217fddf1461057f575f5ffd5b80634f1ef2861161015c5780634f1ef2861461034e57806352d1902d14610361578063539a99a2146103755780635b30e378146103945780635c975abb146103ed578063715018a6146104045780637950a1f1146104185780637bfc417d1461044b5780637ecebe001461046a575f5ffd5b806301ffc9a7146101b9578063144aca35146101ed578063248a9ca31461022f57806325c522711461026c5780632f2ff15d146102ba57806336568abe146102db5780633659cfe6146102fa57806349f4f6a114610319575b5f5ffd5b3480156101c4575f5ffd5b506101d86101d3366004612940565b6106a7565b60405190151581526020015b60405180910390f35b3480156101f8575f5ffd5b50610222610207366004612967565b6101026020525f90815260409020546001600160a01b031681565b6040516101e4919061297e565b34801561023a575f5ffd5b5061025e610249366004612967565b5f90815261015f602052604090206001015490565b6040519081526020016101e4565b348015610277575f5ffd5b506040805180820190915260038152620312e360ec1b60209091015261025e7fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b381565b3480156102c5575f5ffd5b506102d96102d43660046129a8565b6106d1565b005b3480156102e6575f5ffd5b506102d96102f53660046129a8565b6106fb565b348015610305575f5ffd5b506102d96103143660046129d2565b61077e565b348015610324575f5ffd5b50610222610333366004612967565b6101036020525f90815260409020546001600160a01b031681565b6102d961035c366004612ab0565b610845565b34801561036c575f5ffd5b5061025e6108fa565b348015610380575f5ffd5b5060fe54610222906001600160a01b031681565b34801561039f575f5ffd5b5060408051808201909152600e81526d13d99998da185a5b94995c1bdc9d60921b60209091015261025e7fbab090260d0616f3025414422730bc27dc7b2a2f888694527569a75de342aecb81565b3480156103f8575f5ffd5b5060655460ff166101d8565b34801561040f575f5ffd5b506102d96109a6565b348015610423575f5ffd5b506102227f000000000000000000000000000000000000000000000000000000000000000081565b348015610456575f5ffd5b506102d9610465366004612b3a565b6109b9565b348015610475575f5ffd5b5061025e6104843660046129d2565b6001600160a01b03165f908152610105602052604090205490565b3480156104aa575f5ffd5b5061025e6101015481565b3480156104c0575f5ffd5b506033546001600160a01b0316610222565b3480156104dd575f5ffd5b506102226104ec366004612bd8565b610b37565b3480156104fc575f5ffd5b506101d861050b3660046129a8565b610b56565b34801561051b575f5ffd5b5060fd54610222906001600160a01b031681565b34801561053a575f5ffd5b5061054e610549366004612c0e565b610b81565b604080519283526001600160a01b039091166020830152016101e4565b348015610576575f5ffd5b506102d9610ba0565b34801561058a575f5ffd5b5061025e5f81565b34801561059d575f5ffd5b506102d96105ac366004612c4f565b610bde565b3480156105bc575f5ffd5b50610222610e0a565b3480156105d0575f5ffd5b5060fc54610222906001600160a01b031681565b3480156105ef575f5ffd5b506102d9610e18565b348015610603575f5ffd5b5061025e610612366004612967565b610e56565b348015610622575f5ffd5b506102d96106313660046129a8565b610e6d565b348015610641575f5ffd5b506102d96106503660046129d2565b610e92565b348015610660575f5ffd5b506102d961066f366004612cbf565b610f08565b34801561067f575f5ffd5b506102227f000000000000000000000000f02bd811d74e5b3e1866bd19e1b8451d48f58bd681565b5f6001600160e01b03198216635a05180f60e01b14806106cb57506106cb82611090565b92915050565b5f82815261015f60205260409020600101546106ec816110c4565b6106f683836110ce565b505050565b6001600160a01b03811633146107705760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b60648201526084015b60405180910390fd5b61077a82826110f0565b5050565b6001600160a01b037f000000000000000000000000fe086d57e17e58324a3bb98ba6ed9f28376cc0181630036107c65760405162461bcd60e51b815260040161076790612d38565b7f000000000000000000000000fe086d57e17e58324a3bb98ba6ed9f28376cc0186001600160a01b03166107f8611112565b6001600160a01b03161461081e5760405162461bcd60e51b815260040161076790612d84565b6108278161112d565b604080515f8082526020820190925261084291839190611137565b50565b6001600160a01b037f000000000000000000000000fe086d57e17e58324a3bb98ba6ed9f28376cc01816300361088d5760405162461bcd60e51b815260040161076790612d38565b7f000000000000000000000000fe086d57e17e58324a3bb98ba6ed9f28376cc0186001600160a01b03166108bf611112565b6001600160a01b0316146108e55760405162461bcd60e51b815260040161076790612d84565b6108ee8261112d565b61077a82826001611137565b5f306001600160a01b037f000000000000000000000000fe086d57e17e58324a3bb98ba6ed9f28376cc01816146109945760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c6044820152771b1959081d1a1c9bdd59da0819195b1959d85d1958d85b1b60421b6064820152608401610767565b505f516020613d7d5f395f51905f5290565b6109ae6112a1565b6109b75f6112fb565b565b5f6109c3816110c4565b838281146109e45760405163586cb9e160e01b815260040160405180910390fd5b6109ef89898961134c565b5f5b81811015610b2b575f878783818110610a0c57610a0c612dd0565b9050602002016020810190610a2191906129d2565b6001600160a01b031603610a48576040516366385fa360e01b815260040160405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634697f05d888884818110610a8957610a89612dd0565b9050602002016020810190610a9e91906129d2565b878785818110610ab057610ab0612dd0565b9050602002016020810190610ac59190612dfc565b6040516001600160e01b031960e085901b1681526001600160a01b039092166004830152151560248201526044015f604051808303815f87803b158015610b0a575f5ffd5b505af1158015610b1c573d5f5f3e3d5ffd5b505050508060010190506109f1565b50505050505050505050565b5f82815261019160205260408120610b4f90836113d8565b9392505050565b5f91825261015f602090815260408084206001600160a01b0393909316845291905290205460ff1690565b5f80610b94610b8f84612e17565b6113e3565b60209093013593915050565b610ba8611441565b604051602001610bb790612eaa565b60405160208183030381529060405280519060200120610bd6816110c4565b61084261148a565b5f548190610100900460ff16158015610bfd57505f5460ff8083169116105b610c605760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610767565b5f805461ffff191660ff831617610100179055610c7b6114d6565b610c836114fc565b6001600160a01b038416610caa576040516366385fa360e01b815260040160405180910390fd5b610cb35f610e56565b15801590610cc85750610cc65f33610b56565b155b15610ce85733604051635486d5fd60e11b8152600401610767919061297e565b610cf15f610e56565b5f03610d5d57610d015f856110ce565b610d2f604051602001610d1390612eaa565b60405160208183030381529060405280519060200120856110ce565b610d5d604051602001610d4190612ed7565b60405160208183030381529060405280519060200120846110ce565b6001600160a01b038516610d84576040516366385fa360e01b815260040160405180910390fd5b60fc80546001600160a01b038781166001600160a01b03199283161790925560fd80548a841690831617905560fe8054928916929091169190911790555f805461ff001916905560405160ff821681527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150505050505050565b5f610e13611112565b905090565b610e20611514565b604051602001610e2f90612eaa565b60405160208183030381529060405280519060200120610e4e816110c4565b61084261155a565b5f818152610191602052604081206106cb90611597565b5f82815261015f6020526040902060010154610e88816110c4565b6106f683836110f0565b610e9a6112a1565b6001600160a01b038116610eff5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610767565b610842816112fb565b610f10611514565b5f80610f27858585610f228580610b37565b6115a0565b604051634c1d96ab60e11b815291935091506001600160a01b0383169063983b2d5690610f5890849060040161297e565b5f604051808303815f87803b158015610f6f575f5ffd5b505af1158015610f81573d5f5f3e3d5ffd5b50505050816001600160a01b03166336568abe604051602001610fcf90602080825260179082015276544f4b454e5f4d494e5445525f41444d494e5f524f4c4560481b604082015260600190565b60408051601f198184030181529082905280516020909101206001600160e01b031960e084901b16825260048201523060248201526044015f604051808303815f87803b15801561101e575f5ffd5b505af1158015611030573d5f5f3e3d5ffd5b5050610101545f81815261010360209081526040808320546101029092528083205490516001600160a01b039283169650911693507ff3891eaa15d438132be54582fa326e471227aacade9ebed32006b0ba9d63254c9190a45050505050565b5f6001600160e01b03198216637965db0b60e01b14806106cb57506301ffc9a760e01b6001600160e01b03198316146106cb565b61084281336119c0565b6110d88282611a19565b5f828152610191602052604090206106f69082611a9f565b6110fa8282611ab3565b5f828152610191602052604090206106f69082611b1a565b5f516020613d7d5f395f51905f52546001600160a01b031690565b5f61077a816110c4565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561116a576106f683611b2e565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156111c4575060408051601f3d908101601f191682019092526111c191810190612f0e565b60015b6112275760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610767565b5f516020613d7d5f395f51905f5281146112955760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610767565b506106f6838383611bc9565b6033546001600160a01b031633146109b75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610767565b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b038316158061136957506001600160a01b038216155b8061137b57506001600160a01b038116155b15611399576040516366385fa360e01b815260040160405180910390fd5b60fc80546001600160a01b039485166001600160a01b03199182161790915560fd80549385169382169390931790925560fe8054919093169116179055565b5f610b4f8383611bf3565b5f6113ed82611c19565b905061141d60405160200161140190612ed7565b6040516020818303038152906040528051906020012082610b56565b61143c578060405163bf18af4360e01b8152600401610767919061297e565b919050565b60655460ff166109b75760405162461bcd60e51b815260206004820152601460248201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b6044820152606401610767565b611492611441565b6065805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516114cc919061297e565b60405180910390a1565b5f54610100900460ff166109b75760405162461bcd60e51b815260040161076790612f25565b611504611d0f565b61150c611d3d565b6109b76114d6565b60655460ff16156109b75760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610767565b611562611514565b6065805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586114bf3390565b5f6106cb825490565b5f5f6115ac8585611d6b565b5f6115ba60e0880188612f70565b91508190506115cd610100890189612f70565b9050146115ed5760405163586cb9e160e01b815260040160405180910390fd5b5f805b828110156116315761160560e08a018a612f70565b8281811061161557611615612dd0565b90506020020135826116279190612fc9565b91506001016115f0565b506116426080890160608a01612ff2565b6001600160e01b03161580159061167057506116646080890160608a01612ff2565b6001600160e01b031681115b1561168e57604051637526372f60e01b815260040160405180910390fd5b6001600160e01b038111156116b657604051637ac7b99d60e11b815260040160405180910390fd5b6101015f81546116c59061300b565b909155505060fd546001600160a01b0316905083876116ea6080890160608a016129d2565b8660026040516024016117009493929190613146565b60408051601f198184030181529181526020820180516001600160e01b031663585873f560e11b1790525161173490612933565b611740939291906132d7565b604051809103905ff080158015611759573d5f5f3e3d5ffd5b5061010180545f908152610102602052604080822080546001600160a01b0319166001600160a01b0395861617905560fe5492548252902054908216918591166117a96080890160608a016129d2565b866117ba60a08c0160808d016129d2565b7f000000000000000000000000f02bd811d74e5b3e1866bd19e1b8451d48f58bd66117eb60c08e0160a08f016129d2565b8d60c00160208101906117fe9190612dfc565b60fc546040516001600160a01b03988916602482015296881660448801529487166064870152928616608486015290851660a4850152841660c4840152151560e483015282166101048201527f000000000000000000000000000000000000000000000000000000000000000090911661012482015260026101448201526101640160408051601f198184030181529181526020820180516001600160e01b031663103fb0bb60e21b179052516118b490612933565b6118c0939291906132d7565b604051809103905ff0801580156118d9573d5f5f3e3d5ffd5b5061010180545f908152610103602052604080822080546001600160a01b0319166001600160a01b0395861617905591548152819020549051634697f05d60e01b81529082166004820152600160248201527f000000000000000000000000000000000000000000000000000000000000000090911690634697f05d906044015f604051808303815f87803b158015611970575f5ffd5b505af1158015611982573d5f5f3e3d5ffd5b5050610101545f9081526101026020908152604080832054610103909252909120546001600160a01b03918216955016925050505b94509492505050565b6119ca8282610b56565b61077a576119d781611f12565b6119e2836020611f24565b6040516020016119f3929190613319565b60408051601f198184030181529082905262461bcd60e51b825261076791600401613368565b611a238282610b56565b61077a575f82815261015f602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611a5b3390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b5f610b4f836001600160a01b0384166120b9565b611abd8282610b56565b1561077a575f82815261015f602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b5f610b4f836001600160a01b038416612105565b6001600160a01b0381163b611b9b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610767565b5f516020613d7d5f395f51905f5280546001600160a01b0319166001600160a01b0392909216919091179055565b611bd2836121e8565b5f82511180611bde5750805b156106f657611bed8383612227565b50505050565b5f825f018281548110611c0857611c08612dd0565b905f5260205f200154905092915050565b60808101515f9042811015611c4a57604051636dd0bf4d60e11b815260048101829052426024820152604401610767565b5f7fac220aa699471afa03226e7e5c75686e50f65febb8df455cb4ff126c688be28d845f0151856020015186604001518760600151868960a00151604051602001611cd497969594939291909687526001600160a01b03958616602088015260408701949094529184166060860152909216608084015260a083019190915260c082015260e00190565b6040516020818303038152906040528051906020012090505f611cf68261224c565b9050611d06818660c0015161234a565b95945050505050565b5f54610100900460ff16611d355760405162461bcd60e51b815260040161076790612f25565b6109b761236c565b5f54610100900460ff16611d635760405162461bcd60e51b815260040161076790612f25565b6109b761239b565b5f5f611d7684610b81565b91509150611da1816001600160a01b03165f9081526101056020526040902080546001810190915590565b505f611db060208601866129d2565b90508215611f0b57833515611e8c576001600160a01b03811663d505accf611dde60408701602088016129d2565b611dee60608801604089016129d2565b60608801358835611e0560a08b0160808c0161337a565b6040516001600160e01b031960e088901b1681526001600160a01b0395861660048201529490931660248501526044840191909152606483015260ff16608482015260a087013560a482015260c087013560c482015260e4015f604051808303815f87803b158015611e75575f5ffd5b505af1158015611e87573d5f5f3e3d5ffd5b505050505b611eb281611ea060608801604089016129d2565b60fc546001600160a01b0316866123cd565b611ec260608601604087016129d2565b604080516001600160a01b0384811682526020820187905292909216917fc0d39cf3434f9dede81e427dbbccd901073df1b746711cb6cb7db1b27ddd6927910160405180910390a25b5050505050565b60606106cb6001600160a01b03831660145b60605f611f32836002613393565b611f3d906002612fc9565b6001600160401b03811115611f5457611f546129eb565b6040519080825280601f01601f191660200182016040528015611f7e576020820181803683370190505b509050600360fc1b815f81518110611f9857611f98612dd0565b60200101906001600160f81b03191690815f1a905350600f60fb1b81600181518110611fc657611fc6612dd0565b60200101906001600160f81b03191690815f1a9053505f611fe8846002613393565b611ff3906001612fc9565b90505b600181111561206a576f181899199a1a9b1b9c1cb0b131b232b360811b85600f166010811061202757612027612dd0565b1a60f81b82828151811061203d5761203d612dd0565b60200101906001600160f81b03191690815f1a90535060049490941c93612063816133aa565b9050611ff6565b508315610b4f5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610767565b5f8181526001830160205260408120546120fe57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556106cb565b505f6106cb565b5f81815260018301602052604081205480156121df575f6121276001836133bf565b85549091505f9061213a906001906133bf565b9050818114612199575f865f01828154811061215857612158612dd0565b905f5260205f200154905080875f01848154811061217857612178612dd0565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806121aa576121aa6133d2565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506106cb565b5f9150506106cb565b6121f181611b2e565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b6060610b4f8383604051806060016040528060278152602001613d9d60279139612427565b5f6106cb61232a604080518082018252600e81526d13d99998da185a5b94995c1bdc9d60921b6020918201528151808301835260038152620312e360ec1b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527fbab090260d0616f3025414422730bc27dc7b2a2f888694527569a75de342aecb818401527fe6bbd6277e1bf288eed5e8d1780f9a50b239e86b153736bceebccf4ea79d90b360608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b8360405161190160f01b8152600281019290925260228201526042902090565b5f5f5f612357858561249b565b91509150612364816124dd565b509392505050565b5f54610100900460ff166123925760405162461bcd60e51b815260040161076790612f25565b6109b7336112fb565b5f54610100900460ff166123c15760405162461bcd60e51b815260040161076790612f25565b6065805460ff19169055565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611bed908590612621565b60605f5f856001600160a01b03168560405161244391906133e6565b5f60405180830381855af49150503d805f811461247b576040519150601f19603f3d011682016040523d82523d5f602084013e612480565b606091505b5091509150612491868383876126f4565b9695505050505050565b5f5f82516041036124cf576020830151604084015160608501515f1a6124c387828585612774565b945094505050506124d6565b505f905060025b9250929050565b5f8160048111156124f0576124f06133f1565b036124f85750565b600181600481111561250c5761250c6133f1565b036125545760405162461bcd60e51b815260206004820152601860248201527745434453413a20696e76616c6964207369676e617475726560401b6044820152606401610767565b6002816004811115612568576125686133f1565b036125b55760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610767565b60038160048111156125c9576125c96133f1565b036108425760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610767565b5f612675826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166128249092919063ffffffff16565b905080515f14806126955750808060200190518101906126959190613405565b6106f65760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610767565b606083156127625782515f0361275b576001600160a01b0385163b61275b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610767565b508161276c565b61276c8383612832565b949350505050565b5f806fa2a8918ca85bafe22016d0b997e4df60600160ff1b0383111561279f57505f905060036119b7565b604080515f8082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156127f0573d5f5f3e3d5ffd5b5050604051601f1901519150506001600160a01b038116612818575f600192509250506119b7565b965f9650945050505050565b606061276c84845f8561285c565b8151156128425781518083602001fd5b8060405162461bcd60e51b81526004016107679190613368565b6060824710156128bd5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610767565b5f5f866001600160a01b031685876040516128d891906133e6565b5f6040518083038185875af1925050503d805f8114612912576040519150601f19603f3d011682016040523d82523d5f602084013e612917565b606091505b5091509150612928878383876126f4565b979650505050505050565b61095c8061342183390190565b5f60208284031215612950575f5ffd5b81356001600160e01b031981168114610b4f575f5ffd5b5f60208284031215612977575f5ffd5b5035919050565b6001600160a01b0391909116815260200190565b80356001600160a01b038116811461143c575f5ffd5b5f5f604083850312156129b9575f5ffd5b823591506129c960208401612992565b90509250929050565b5f602082840312156129e2575f5ffd5b610b4f82612992565b634e487b7160e01b5f52604160045260245ffd5b60405160e081016001600160401b0381118282101715612a2157612a216129eb565b60405290565b5f82601f830112612a36575f5ffd5b81356001600160401b03811115612a4f57612a4f6129eb565b604051601f8201601f19908116603f011681016001600160401b0381118282101715612a7d57612a7d6129eb565b604052818152838201602001851015612a94575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f5f60408385031215612ac1575f5ffd5b612aca83612992565b915060208301356001600160401b03811115612ae4575f5ffd5b612af085828601612a27565b9150509250929050565b5f5f83601f840112612b0a575f5ffd5b5081356001600160401b03811115612b20575f5ffd5b6020830191508360208260051b85010111156124d6575f5ffd5b5f5f5f5f5f5f5f60a0888a031215612b50575f5ffd5b612b5988612992565b9650612b6760208901612992565b9550612b7560408901612992565b945060608801356001600160401b03811115612b8f575f5ffd5b612b9b8a828b01612afa565b90955093505060808801356001600160401b03811115612bb9575f5ffd5b612bc58a828b01612afa565b989b979a50959850939692959293505050565b5f5f60408385031215612be9575f5ffd5b50508035926020909101359150565b5f60e08284031215612c08575f5ffd5b50919050565b5f60208284031215612c1e575f5ffd5b81356001600160401b03811115612c33575f5ffd5b61276c84828501612bf8565b803560ff8116811461143c575f5ffd5b5f5f5f5f5f5f60c08789031215612c64575f5ffd5b612c6d87612992565b9550612c7b60208801612992565b9450612c8960408801612992565b9350612c9760608801612992565b9250612ca560808801612992565b9150612cb360a08801612c3f565b90509295509295509295565b5f5f5f6101208486031215612cd2575f5ffd5b83356001600160401b03811115612ce7575f5ffd5b84016101208187031215612cf9575f5ffd5b925060208401356001600160401b03811115612d13575f5ffd5b612d1f86828701612bf8565b925050612d2f8560408601612bf8565b90509250925092565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b5f52603260045260245ffd5b8015158114610842575f5ffd5b803561143c81612de4565b5f60208284031215612e0c575f5ffd5b8135610b4f81612de4565b5f60e08236031215612e27575f5ffd5b612e2f6129ff565b612e3883612992565b815260208381013590820152612e5060408401612992565b6040820152612e6160608401612992565b60608201526080838101359082015260a0808401359082015260c08301356001600160401b03811115612e92575f5ffd5b612e9e36828601612a27565b60c08301525092915050565b602080825260139082015272464143544f52595f5041555345525f524f4c4560681b604082015260600190565b6020808252601e908201527f464143544f52595f4f4646434841494e5f5245504f525445525f524f4c450000604082015260600190565b5f60208284031215612f1e575f5ffd5b5051919050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b5f5f8335601e19843603018112612f85575f5ffd5b8301803591506001600160401b03821115612f9e575f5ffd5b6020019150600581901b36038213156124d6575f5ffd5b634e487b7160e01b5f52601160045260245ffd5b808201808211156106cb576106cb612fb5565b80356001600160e01b038116811461143c575f5ffd5b5f60208284031215613002575f5ffd5b610b4f82612fdc565b5f6001820161301c5761301c612fb5565b5060010190565b5f5f8335601e19843603018112613038575f5ffd5b83016020810192503590506001600160401b03811115613056575f5ffd5b8036038213156124d6575f5ffd5b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b5f5f8335601e198436030181126130a1575f5ffd5b83016020810192503590506001600160401b038111156130bf575f5ffd5b8060051b36038213156124d6575f5ffd5b8183525f6001600160fb1b038311156130e7575f5ffd5b8260051b80836020870137939093016020019392505050565b8183526020830192505f815f5b8481101561313c576001600160a01b0361312683612992565b168652602095860195919091019060010161310d565b5093949350505050565b608081525f6131558687613023565b610120608085015261316c6101a085018284613064565b91505061317c6020880188613023565b848303607f190160a0860152613193838284613064565b925050506131a46040880188613023565b848303607f190160c08601526131bb838284613064565b925050506131cb60608801612fdc565b6001600160e01b031660e08401526131e560808801612992565b6001600160a01b031661010084015261320060a08801612992565b6001600160a01b031661012084015261321b60c08801612df1565b151561014084015261323060e088018861308c565b848303607f19016101608601526132488382846130d0565b9250505061325a61010088018861308c565b848303607f1901610180860152613272838284613100565b935050505061328c60208301866001600160a01b03169052565b6001600160a01b038416604083015260ff83166060830152611d06565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b038481168252831660208201526060604082018190525f90611d06908301846132a9565b5f81518060208401855e5f93019283525090919050565b76020b1b1b2b9b9a1b7b73a3937b61d1030b1b1b7bab73a1604d1b81525f6133446017830185613302565b7001034b99036b4b9b9b4b733903937b6329607d1b8152611d066011820185613302565b602081525f610b4f60208301846132a9565b5f6020828403121561338a575f5ffd5b610b4f82612c3f565b80820281158282048414176106cb576106cb612fb5565b5f816133b8576133b8612fb5565b505f190190565b818103818111156106cb576106cb612fb5565b634e487b7160e01b5f52603160045260245ffd5b5f610b4f8284613302565b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215613415575f5ffd5b8151610b4f81612de456fe608060405260405161095c38038061095c833981016040819052610022916102d0565b6001600160a01b038316158061003f57506001600160a01b038216155b1561005d576040516366385fa360e01b815260040160405180910390fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610380546001600160a01b0319166001600160a01b038416179055827fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d5080546001600160a01b0319166001600160a01b039290921691909117905580511561014957610147836001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561011d573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061014191906103a1565b82610151565b505b505050610405565b606061017683836040518060600160405280602781526020016109356027913961017d565b9392505050565b60605f5f856001600160a01b03168560405161019991906103ba565b5f60405180830381855af49150503d805f81146101d1576040519150601f19603f3d011682016040523d82523d5f602084013e6101d6565b606091505b5090925090506101e8868383876101f2565b9695505050505050565b606083156102655782515f0361025e576001600160a01b0385163b61025e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064015b60405180910390fd5b508161026f565b61026f8383610277565b949350505050565b8151156102875781518083602001fd5b8060405162461bcd60e51b815260040161025591906103d0565b80516001600160a01b03811681146102b7575f5ffd5b919050565b634e487b7160e01b5f52604160045260245ffd5b5f5f5f606084860312156102e2575f5ffd5b6102eb846102a1565b92506102f9602085016102a1565b60408501519092506001600160401b03811115610314575f5ffd5b8401601f81018613610324575f5ffd5b80516001600160401b0381111561033d5761033d6102bc565b604051601f8201601f19908116603f011681016001600160401b038111828210171561036b5761036b6102bc565b604052818152828201602001881015610382575f5ffd5b8160208401602083015e5f602083830101528093505050509250925092565b5f602082840312156103b1575f5ffd5b610176826102a1565b5f82518060208501845e5f920191825250919050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b610523806104125f395ff3fe608060405260043610610042575f3560e01c8063611726df146100595780639f712f2f14610078578063aaf10f4214610097578063bebc0fbf146100c757610051565b366100515761004f6100e6565b005b61004f6100e6565b348015610064575f5ffd5b5061004f610073366004610494565b6100f8565b348015610083575f5ffd5b5061004f610092366004610494565b6101d6565b3480156100a2575f5ffd5b506100ab610217565b6040516001600160a01b03909116815260200160405180910390f35b3480156100d2575f5ffd5b5061004f6100e1366004610494565b610225565b6100f66100f161028e565b610315565b565b610100610333565b6001600160a01b0316336001600160a01b0316146101395760405162461bcd60e51b8152600401610130906104b6565b60405180910390fd5b6001600160a01b0381166101a15760405162461bcd60e51b815260206004820152602960248201527f426561636f6e50726f78793a2066696e616c20696d706c656d656e746174696f6044820152681b881a5cc81b9d5b1b60ba1b6064820152608401610130565b5f5160206105035f395f51905f5280546001600160a01b0319166001600160a01b0383161790556101d361dead610365565b50565b6101de610333565b6001600160a01b0316336001600160a01b03161461020e5760405162461bcd60e51b8152600401610130906104b6565b6101d381610365565b5f61022061028e565b905090565b61022d610333565b6001600160a01b0316336001600160a01b03161461025d5760405162461bcd60e51b8152600401610130906104b6565b805f5160206105035f395f51905f525b80546001600160a01b0319166001600160a01b039290921691909117905550565b5f806102986103b9565b6001600160a01b0316146102ae576102206103b9565b6102b66103cd565b6001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102f1573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061022091906104e7565b365f5f375f5f365f845af43d5f5f3e80801561032f573d5ff35b3d5ffd5b5f7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61038e610333565b604080516001600160a01b03928316815291841660208301520160405180910390a16101d3816103f4565b5f5f5160206105035f395f51905f52610356565b5f7fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50610356565b6001600160a01b0381166104595760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b6064820152608401610130565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610361026d565b6001600160a01b03811681146101d3575f5ffd5b5f602082840312156104a4575f5ffd5b81356104af81610480565b9392505050565b6020808252601790820152762132b0b1b7b7283937bc3c9d1037b7363c9030b236b4b760491b604082015260600190565b5f602082840312156104f7575f5ffd5b81516104af8161048056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564