文件 1 的 27:ABDKMath64x64.sol
pragma solidity ^0.8.4;
library ABDKMath64x64 {
int128 private constant MIN_64x64 = -0x80000000000000000000000000000000;
int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
function fromInt (int256 x) internal pure returns (int128) {
unchecked {
require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF);
return int128 (x << 64);
}
}
function toInt (int128 x) internal pure returns (int64) {
unchecked {
return int64 (x >> 64);
}
}
function fromUInt (uint256 x) internal pure returns (int128) {
unchecked {
require (x <= 0x7FFFFFFFFFFFFFFF);
return int128 (int256 (x << 64));
}
}
function toUInt (int128 x) internal pure returns (uint64) {
unchecked {
require (x >= 0);
return uint64 (uint128 (x >> 64));
}
}
function from128x128 (int256 x) internal pure returns (int128) {
unchecked {
int256 result = x >> 64;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function to128x128 (int128 x) internal pure returns (int256) {
unchecked {
return int256 (x) << 64;
}
}
function add (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) + y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function sub (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) - y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function mul (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 result = int256(x) * y >> 64;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function muli (int128 x, int256 y) internal pure returns (int256) {
unchecked {
if (x == MIN_64x64) {
require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF &&
y <= 0x1000000000000000000000000000000000000000000000000);
return -y << 63;
} else {
bool negativeResult = false;
if (x < 0) {
x = -x;
negativeResult = true;
}
if (y < 0) {
y = -y;
negativeResult = !negativeResult;
}
uint256 absoluteResult = mulu (x, uint256 (y));
if (negativeResult) {
require (absoluteResult <=
0x8000000000000000000000000000000000000000000000000000000000000000);
return -int256 (absoluteResult);
} else {
require (absoluteResult <=
0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int256 (absoluteResult);
}
}
}
}
function mulu (int128 x, uint256 y) internal pure returns (uint256) {
unchecked {
if (y == 0) return 0;
require (x >= 0);
uint256 lo = (uint256 (int256 (x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64;
uint256 hi = uint256 (int256 (x)) * (y >> 128);
require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
hi <<= 64;
require (hi <=
0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo);
return hi + lo;
}
}
function div (int128 x, int128 y) internal pure returns (int128) {
unchecked {
require (y != 0);
int256 result = (int256 (x) << 64) / y;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function divi (int256 x, int256 y) internal pure returns (int128) {
unchecked {
require (y != 0);
bool negativeResult = false;
if (x < 0) {
x = -x;
negativeResult = true;
}
if (y < 0) {
y = -y;
negativeResult = !negativeResult;
}
uint128 absoluteResult = divuu (uint256 (x), uint256 (y));
if (negativeResult) {
require (absoluteResult <= 0x80000000000000000000000000000000);
return -int128 (absoluteResult);
} else {
require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return int128 (absoluteResult);
}
}
}
function divu (uint256 x, uint256 y) internal pure returns (int128) {
unchecked {
require (y != 0);
uint128 result = divuu (x, y);
require (result <= uint128 (MAX_64x64));
return int128 (result);
}
}
function neg (int128 x) internal pure returns (int128) {
unchecked {
require (x != MIN_64x64);
return -x;
}
}
function abs (int128 x) internal pure returns (int128) {
unchecked {
require (x != MIN_64x64);
return x < 0 ? -x : x;
}
}
function inv (int128 x) internal pure returns (int128) {
unchecked {
require (x != 0);
int256 result = int256 (0x100000000000000000000000000000000) / x;
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function avg (int128 x, int128 y) internal pure returns (int128) {
unchecked {
return int128 ((int256 (x) + int256 (y)) >> 1);
}
}
function gavg (int128 x, int128 y) internal pure returns (int128) {
unchecked {
int256 m = int256 (x) * int256 (y);
require (m >= 0);
require (m <
0x4000000000000000000000000000000000000000000000000000000000000000);
return int128 (sqrtu (uint256 (m)));
}
}
function pow (int128 x, uint256 y) internal pure returns (int128) {
unchecked {
bool negative = x < 0 && y & 1 == 1;
uint256 absX = uint128 (x < 0 ? -x : x);
uint256 absResult;
absResult = 0x100000000000000000000000000000000;
if (absX <= 0x10000000000000000) {
absX <<= 63;
while (y != 0) {
if (y & 0x1 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x2 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x4 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
if (y & 0x8 != 0) {
absResult = absResult * absX >> 127;
}
absX = absX * absX >> 127;
y >>= 4;
}
absResult >>= 64;
} else {
uint256 absXShift = 63;
if (absX < 0x1000000000000000000000000) { absX <<= 32; absXShift -= 32; }
if (absX < 0x10000000000000000000000000000) { absX <<= 16; absXShift -= 16; }
if (absX < 0x1000000000000000000000000000000) { absX <<= 8; absXShift -= 8; }
if (absX < 0x10000000000000000000000000000000) { absX <<= 4; absXShift -= 4; }
if (absX < 0x40000000000000000000000000000000) { absX <<= 2; absXShift -= 2; }
if (absX < 0x80000000000000000000000000000000) { absX <<= 1; absXShift -= 1; }
uint256 resultShift = 0;
while (y != 0) {
require (absXShift < 64);
if (y & 0x1 != 0) {
absResult = absResult * absX >> 127;
resultShift += absXShift;
if (absResult > 0x100000000000000000000000000000000) {
absResult >>= 1;
resultShift += 1;
}
}
absX = absX * absX >> 127;
absXShift <<= 1;
if (absX >= 0x100000000000000000000000000000000) {
absX >>= 1;
absXShift += 1;
}
y >>= 1;
}
require (resultShift < 64);
absResult >>= 64 - resultShift;
}
int256 result = negative ? -int256 (absResult) : int256 (absResult);
require (result >= MIN_64x64 && result <= MAX_64x64);
return int128 (result);
}
}
function sqrt (int128 x) internal pure returns (int128) {
unchecked {
require (x >= 0);
return int128 (sqrtu (uint256 (int256 (x)) << 64));
}
}
function log_2 (int128 x) internal pure returns (int128) {
unchecked {
require (x > 0);
int256 msb = 0;
int256 xc = x;
if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; }
if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
if (xc >= 0x10000) { xc >>= 16; msb += 16; }
if (xc >= 0x100) { xc >>= 8; msb += 8; }
if (xc >= 0x10) { xc >>= 4; msb += 4; }
if (xc >= 0x4) { xc >>= 2; msb += 2; }
if (xc >= 0x2) msb += 1;
int256 result = msb - 64 << 64;
uint256 ux = uint256 (int256 (x)) << uint256 (127 - msb);
for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) {
ux *= ux;
uint256 b = ux >> 255;
ux >>= 127 + b;
result += bit * int256 (b);
}
return int128 (result);
}
}
function ln (int128 x) internal pure returns (int128) {
unchecked {
require (x > 0);
return int128 (int256 (
uint256 (int256 (log_2 (x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128));
}
}
function exp_2 (int128 x) internal pure returns (int128) {
unchecked {
require (x < 0x400000000000000000);
if (x < -0x400000000000000000) return 0;
uint256 result = 0x80000000000000000000000000000000;
if (x & 0x8000000000000000 > 0)
result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128;
if (x & 0x4000000000000000 > 0)
result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128;
if (x & 0x2000000000000000 > 0)
result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128;
if (x & 0x1000000000000000 > 0)
result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128;
if (x & 0x800000000000000 > 0)
result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128;
if (x & 0x400000000000000 > 0)
result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128;
if (x & 0x200000000000000 > 0)
result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128;
if (x & 0x100000000000000 > 0)
result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128;
if (x & 0x80000000000000 > 0)
result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128;
if (x & 0x40000000000000 > 0)
result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128;
if (x & 0x20000000000000 > 0)
result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128;
if (x & 0x10000000000000 > 0)
result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128;
if (x & 0x8000000000000 > 0)
result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128;
if (x & 0x4000000000000 > 0)
result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128;
if (x & 0x2000000000000 > 0)
result = result * 0x1000162E525EE054754457D5995292026 >> 128;
if (x & 0x1000000000000 > 0)
result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128;
if (x & 0x800000000000 > 0)
result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128;
if (x & 0x400000000000 > 0)
result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128;
if (x & 0x200000000000 > 0)
result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128;
if (x & 0x100000000000 > 0)
result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128;
if (x & 0x80000000000 > 0)
result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128;
if (x & 0x40000000000 > 0)
result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128;
if (x & 0x20000000000 > 0)
result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128;
if (x & 0x10000000000 > 0)
result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128;
if (x & 0x8000000000 > 0)
result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128;
if (x & 0x4000000000 > 0)
result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128;
if (x & 0x2000000000 > 0)
result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128;
if (x & 0x1000000000 > 0)
result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128;
if (x & 0x800000000 > 0)
result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128;
if (x & 0x400000000 > 0)
result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128;
if (x & 0x200000000 > 0)
result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128;
if (x & 0x100000000 > 0)
result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128;
if (x & 0x80000000 > 0)
result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128;
if (x & 0x40000000 > 0)
result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128;
if (x & 0x20000000 > 0)
result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128;
if (x & 0x10000000 > 0)
result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128;
if (x & 0x8000000 > 0)
result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128;
if (x & 0x4000000 > 0)
result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128;
if (x & 0x2000000 > 0)
result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128;
if (x & 0x1000000 > 0)
result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128;
if (x & 0x800000 > 0)
result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128;
if (x & 0x400000 > 0)
result = result * 0x100000000002C5C85FDF477B662B26945 >> 128;
if (x & 0x200000 > 0)
result = result * 0x10000000000162E42FEFA3AE53369388C >> 128;
if (x & 0x100000 > 0)
result = result * 0x100000000000B17217F7D1D351A389D40 >> 128;
if (x & 0x80000 > 0)
result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128;
if (x & 0x40000 > 0)
result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128;
if (x & 0x20000 > 0)
result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128;
if (x & 0x10000 > 0)
result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128;
if (x & 0x8000 > 0)
result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128;
if (x & 0x4000 > 0)
result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128;
if (x & 0x2000 > 0)
result = result * 0x1000000000000162E42FEFA39F02B772C >> 128;
if (x & 0x1000 > 0)
result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128;
if (x & 0x800 > 0)
result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128;
if (x & 0x400 > 0)
result = result * 0x100000000000002C5C85FDF473DEA871F >> 128;
if (x & 0x200 > 0)
result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128;
if (x & 0x100 > 0)
result = result * 0x100000000000000B17217F7D1CF79E949 >> 128;
if (x & 0x80 > 0)
result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128;
if (x & 0x40 > 0)
result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128;
if (x & 0x20 > 0)
result = result * 0x100000000000000162E42FEFA39EF366F >> 128;
if (x & 0x10 > 0)
result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128;
if (x & 0x8 > 0)
result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128;
if (x & 0x4 > 0)
result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128;
if (x & 0x2 > 0)
result = result * 0x1000000000000000162E42FEFA39EF358 >> 128;
if (x & 0x1 > 0)
result = result * 0x10000000000000000B17217F7D1CF79AB >> 128;
result >>= uint256 (int256 (63 - (x >> 64)));
require (result <= uint256 (int256 (MAX_64x64)));
return int128 (int256 (result));
}
}
function exp (int128 x) internal pure returns (int128) {
unchecked {
require (x < 0x400000000000000000);
if (x < -0x400000000000000000) return 0;
return exp_2 (
int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128));
}
}
function divuu (uint256 x, uint256 y) private pure returns (uint128) {
unchecked {
require (y != 0);
uint256 result;
if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
result = (x << 64) / y;
else {
uint256 msb = 192;
uint256 xc = x >> 192;
if (xc >= 0x100000000) { xc >>= 32; msb += 32; }
if (xc >= 0x10000) { xc >>= 16; msb += 16; }
if (xc >= 0x100) { xc >>= 8; msb += 8; }
if (xc >= 0x10) { xc >>= 4; msb += 4; }
if (xc >= 0x4) { xc >>= 2; msb += 2; }
if (xc >= 0x2) msb += 1;
result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1);
require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 hi = result * (y >> 128);
uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
uint256 xh = x >> 192;
uint256 xl = x << 64;
if (xl < lo) xh -= 1;
xl -= lo;
lo = hi << 128;
if (xl < lo) xh -= 1;
xl -= lo;
assert (xh == hi >> 128);
result += xl / y;
}
require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return uint128 (result);
}
}
function sqrtu (uint256 x) private pure returns (uint128) {
unchecked {
if (x == 0) return 0;
else {
uint256 xx = x;
uint256 r = 1;
if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; }
if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; }
if (xx >= 0x100000000) { xx >>= 32; r <<= 16; }
if (xx >= 0x10000) { xx >>= 16; r <<= 8; }
if (xx >= 0x100) { xx >>= 8; r <<= 4; }
if (xx >= 0x10) { xx >>= 4; r <<= 2; }
if (xx >= 0x8) { r <<= 1; }
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
r = (r + x / r) >> 1;
uint256 r1 = x / r;
return uint128 (r < r1 ? r : r1);
}
}
}
}
文件 2 的 27:AccessControl.sol
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role, _msgSender());
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view override returns (bool) {
return _roles[role].members[account];
}
function _checkRole(bytes32 role, address account) internal view {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(uint160(account), 20),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) private {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 3 的 27:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 4 的 27:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 5 的 27:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 6 的 27:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
文件 7 的 27:ERC20Burnable.sol
pragma solidity ^0.8.0;
import "../ERC20.sol";
import "../../../utils/Context.sol";
abstract contract ERC20Burnable is Context, ERC20 {
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
function burnFrom(address account, uint256 amount) public virtual {
uint256 currentAllowance = allowance(account, _msgSender());
require(currentAllowance >= amount, "ERC20: burn amount exceeds allowance");
unchecked {
_approve(account, _msgSender(), currentAllowance - amount);
}
_burn(account, amount);
}
}
文件 8 的 27:ExitQueue.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract ExitQueue is Ownable {
struct User {
uint256 Amount;
uint256 FirstExitEpoch;
uint256 LastExitEpoch;
mapping(uint256 => uint256) Exits;
}
mapping(uint256 => uint256) public totalPerEpoch;
mapping(address => User) public userData;
IERC20 public TEMPLE;
uint256 public maxPerEpoch;
uint256 public maxPerAddress;
uint256 public epochSize;
uint256 public firstBlock;
uint256 public nextUnallocatedEpoch;
event JoinQueue(address exiter, uint256 amount);
event Withdrawal(address exiter, uint256 amount);
constructor(
address _TEMPLE,
uint256 _maxPerEpoch,
uint256 _maxPerAddress,
uint256 _epochSize) {
TEMPLE = IERC20(_TEMPLE);
maxPerEpoch = _maxPerEpoch;
maxPerAddress = _maxPerAddress;
epochSize = _epochSize;
firstBlock = block.number;
nextUnallocatedEpoch = 0;
}
function setMaxPerEpoch(uint256 _maxPerEpoch) external onlyOwner {
maxPerEpoch = _maxPerEpoch;
}
function setMaxPerAddress(uint256 _maxPerAddress) external onlyOwner {
maxPerAddress = _maxPerAddress;
}
function setEpochSize(uint256 _epochSize) external onlyOwner {
epochSize = _epochSize;
}
function setStartingBlock(uint256 _firstBlock) external onlyOwner {
require(_firstBlock < firstBlock, "Can only move start block back, not forward");
firstBlock = _firstBlock;
}
function currentEpoch() public view returns (uint256) {
return (block.number - firstBlock) / epochSize;
}
function currentEpochAllocation(address _exiter, uint256 _epoch) external view returns (uint256) {
return userData[_exiter].Exits[_epoch];
}
function join(address _exiter, uint256 _amount) external {
require(_amount > 0, "Amount must be > 0");
if (nextUnallocatedEpoch < currentEpoch()) {
nextUnallocatedEpoch = currentEpoch();
}
User storage user = userData[_exiter];
uint256 unallocatedAmount = _amount;
uint256 _nextUnallocatedEpoch = nextUnallocatedEpoch;
uint256 nextAvailableEpochForUser = _nextUnallocatedEpoch;
if (user.LastExitEpoch > nextAvailableEpochForUser) {
nextAvailableEpochForUser = user.LastExitEpoch;
}
while (unallocatedAmount > 0) {
uint256 allocationForEpoch = unallocatedAmount;
if (user.Exits[nextAvailableEpochForUser] + allocationForEpoch > maxPerAddress) {
allocationForEpoch = maxPerAddress - user.Exits[nextAvailableEpochForUser];
}
if (totalPerEpoch[nextAvailableEpochForUser] + allocationForEpoch > maxPerEpoch) {
allocationForEpoch = maxPerEpoch - totalPerEpoch[nextAvailableEpochForUser];
}
if (allocationForEpoch > 0) {
if (user.Amount == 0) {
user.FirstExitEpoch = nextAvailableEpochForUser;
}
user.Amount += allocationForEpoch;
user.Exits[nextAvailableEpochForUser] += allocationForEpoch;
totalPerEpoch[nextAvailableEpochForUser] += allocationForEpoch;
user.LastExitEpoch = nextAvailableEpochForUser;
if (totalPerEpoch[nextAvailableEpochForUser] >= maxPerEpoch) {
_nextUnallocatedEpoch = nextAvailableEpochForUser;
}
unallocatedAmount -= allocationForEpoch;
}
nextAvailableEpochForUser += 1;
}
nextUnallocatedEpoch = _nextUnallocatedEpoch;
SafeERC20.safeTransferFrom(TEMPLE, msg.sender, address(this), _amount);
emit JoinQueue(_exiter, _amount);
}
function withdraw(uint256 epoch) external {
require(epoch < currentEpoch(), "Can only withdraw from past epochs");
User storage user = userData[msg.sender];
uint256 amount = user.Exits[epoch];
delete user.Exits[epoch];
totalPerEpoch[epoch] -= amount;
user.Amount -= amount;
if (user.Amount == 0) {
delete userData[msg.sender];
}
SafeERC20.safeTransfer(TEMPLE, msg.sender, amount);
emit Withdrawal(msg.sender, amount);
}
}
文件 9 的 27:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address account) external;
}
文件 10 的 27:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 11 的 27:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 12 的 27:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 13 的 27:ITreasuryAllocation.sol
pragma solidity ^0.8.4;
interface ITreasuryAllocation {
function reval() external view returns (uint256);
}
文件 14 的 27:LockedOGTemple.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./OGTemple.sol";
contract LockedOGTemple {
struct LockedEntry {
uint256 BalanceOGTemple;
uint256 LockedUntilTimestamp;
}
mapping(address => LockedEntry[]) public locked;
OGTemple public OG_TEMPLE;
event OGTempleLocked(address _staker, uint256 _amount, uint256 _lockedUntil);
event OGTempleWithdraw(address _staker, uint256 _amount);
constructor(OGTemple _OG_TEMPLE) {
OG_TEMPLE = _OG_TEMPLE;
}
function numLocks(address _staker) external view returns(uint256) {
return locked[_staker].length;
}
function lockFor(address _staker, uint256 _amountOGTemple, uint256 _lockedUntilTimestamp) public {
LockedEntry memory lockEntry = LockedEntry({BalanceOGTemple: _amountOGTemple, LockedUntilTimestamp: _lockedUntilTimestamp});
locked[_staker].push(lockEntry);
SafeERC20.safeTransferFrom(OG_TEMPLE, msg.sender, address(this), _amountOGTemple);
emit OGTempleLocked(_staker, _amountOGTemple, _lockedUntilTimestamp);
}
function lock(uint256 _amountOGTemple, uint256 _lockedUntilTimestamp) external {
lockFor(msg.sender, _amountOGTemple, _lockedUntilTimestamp);
}
function withdrawFor(address _staker, uint256 _idx) public {
LockedEntry[] storage lockedEntries = locked[_staker];
require(_idx < lockedEntries.length, "No lock entry at the specified index");
require(lockedEntries[_idx].LockedUntilTimestamp < block.timestamp, "Specified entry is still locked");
LockedEntry memory entry = lockedEntries[_idx];
lockedEntries[_idx] = lockedEntries[lockedEntries.length-1];
lockedEntries.pop();
SafeERC20.safeTransfer(OG_TEMPLE, _staker, entry.BalanceOGTemple);
emit OGTempleWithdraw(_staker, entry.BalanceOGTemple);
}
function withdraw(uint256 _idx) external {
withdrawFor(msg.sender, _idx);
}
}
文件 15 的 27:MintAllowance.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "./TempleERC20Token.sol";
contract MintAllowance is Ownable {
TempleERC20Token TEMPLE;
constructor(TempleERC20Token _TEMPLE) {
TEMPLE = _TEMPLE;
}
function increaseMintAllowance(address _pool, uint256 _amount) external onlyOwner {
SafeERC20.safeTransferFrom(TEMPLE, msg.sender, address(this), _amount);
SafeERC20.safeIncreaseAllowance(TEMPLE, _pool, _amount);
}
function burnUnusedMintAllowance(address _pool) external onlyOwner {
uint256 unusedMintAllowance = TEMPLE.allowance(address(this), _pool);
SafeERC20.safeDecreaseAllowance(TEMPLE, _pool, unusedMintAllowance);
TEMPLE.burn(unusedMintAllowance);
}
}
文件 16 的 27:OGTemple.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract OGTemple is ERC20, ERC20Burnable, Ownable {
constructor() ERC20("OGTemple", "OG_TEMPLE") {}
function mint(address to, uint256 amount) external onlyOwner {
_mint(to, amount);
}
}
文件 17 的 27:OpeningCeremony.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./TempleERC20Token.sol";
import "./SandalwoodToken.sol";
import "./TempleTreasury.sol";
import "./TreasuryManagementProxy.sol";
import "./TempleStaking.sol";
import "./PresaleAllocation.sol";
import "./LockedOGTemple.sol";
contract OpeningCeremony is Ownable, Pausable, AccessControl {
bytes32 public constant CAN_ADD_VERIFIED_USER = keccak256("CAN_ADD_VERIFIED_USER");
uint256 constant SECONDS_IN_DAY = 24 * 60 * 60;
IERC20 public stablecToken;
TempleERC20Token public templeToken;
TempleTreasury public treasury;
TreasuryManagementProxy public treasuryManagement;
TempleStaking public staking;
LockedOGTemple public lockedOGTemple;
uint256 public unlockDelaySeconds = SECONDS_IN_DAY * 7 * 6;
uint256 public mintMultiple = 6;
uint256 public harvestThresholdStablec;
uint256 public inviteThresholdStablec;
uint256 public maxInvitesPerVerifiedUser;
uint256 public globalDoublingIndex = 1;
uint256 public lastUpdatedTimestamp;
struct Limit {
uint256 guestMax;
uint256 verifiedMax;
uint256 verifiedDayOne;
}
Limit public limitStablec = Limit({guestMax: 10000 * 1e18, verifiedMax: 480000 * 1e18, verifiedDayOne: 30000 * 1e18});
Limit public limitTemple = Limit({guestMax: 10000 * 1e18, verifiedMax: 480000 * 1e18, verifiedDayOne: 30000 * 1e18});
struct Factor {
uint256 numerator;
uint256 denominator;
}
Factor public verifiedBonusFactor;
Factor public guestBonusFactor;
struct User {
bool isVerified;
bool isGuest;
uint8 numInvited;
uint256 doublingIndexAtVerification;
uint256 totalSacrificedStablec;
uint256 totalSacrificedTemple;
}
mapping(address => User) public users;
event MintComplete(address minter, uint256 acceptedStablec, uint256 mintedTemple, uint256 bonusTemple, uint256 mintedOGTemple);
event StakeComplete(address staker, uint256 acceptedTemple, uint256 bonusTemple, uint256 mintedOGTemple);
event VerifiedUserAdded(address user);
constructor(
IERC20 _stablecToken,
TempleERC20Token _templeToken,
TempleStaking _staking,
LockedOGTemple _lockedOGTemple,
TempleTreasury _treasury,
TreasuryManagementProxy _treasuryManagement,
uint256 _harvestThresholdStablec,
uint256 _inviteThresholdStablec,
uint256 _maxInvitesPerVerifiedUser,
Factor memory _verifiedBonusFactor,
Factor memory _guestBonusFactor
) {
stablecToken = _stablecToken;
templeToken = _templeToken;
staking = _staking;
lockedOGTemple = _lockedOGTemple;
treasury = _treasury;
treasuryManagement = _treasuryManagement;
harvestThresholdStablec = _harvestThresholdStablec;
inviteThresholdStablec = _inviteThresholdStablec;
maxInvitesPerVerifiedUser = _maxInvitesPerVerifiedUser;
verifiedBonusFactor = _verifiedBonusFactor;
guestBonusFactor = _guestBonusFactor;
lastUpdatedTimestamp = block.timestamp;
_setupRole(DEFAULT_ADMIN_ROLE, owner());
}
function setUnlockDelay(uint256 _unlockDelaySeconds) external onlyOwner {
unlockDelaySeconds = _unlockDelaySeconds;
}
function setMintMultiple(uint256 _mintMultiple) external onlyOwner {
mintMultiple = _mintMultiple;
}
function setHarvestThreshold(uint256 _harvestThresholdStablec) external onlyOwner {
harvestThresholdStablec = _harvestThresholdStablec;
}
function setInviteThreshold(uint256 _inviteThresholdStablec) external onlyOwner {
inviteThresholdStablec = _inviteThresholdStablec;
}
function setMaxInvitesPerVerifiedUser(uint256 _maxInvitesPerVerifiedUser) external onlyOwner {
maxInvitesPerVerifiedUser = _maxInvitesPerVerifiedUser;
}
function setVerifiedBonusFactor(uint256 _numerator, uint256 _denominator) external onlyOwner {
verifiedBonusFactor.numerator = _numerator;
verifiedBonusFactor.denominator = _denominator;
}
function setGuestBonusFactor(uint256 _numerator, uint256 _denominator) external onlyOwner {
guestBonusFactor.numerator = _numerator;
guestBonusFactor.denominator = _denominator;
}
function setLimitStablec(uint256 guestMax, uint256 verifiedMax, uint256 verifiedDayOne) external onlyOwner {
limitStablec.guestMax = guestMax;
limitStablec.verifiedMax = verifiedMax;
limitStablec.verifiedDayOne = verifiedDayOne;
}
function setLimitTemple(uint256 guestMax, uint256 verifiedMax) external onlyOwner {
limitTemple.guestMax = guestMax;
limitTemple.verifiedMax = verifiedMax;
}
function addVerifier(address account) external onlyOwner {
grantRole(CAN_ADD_VERIFIED_USER, account);
}
function removeVerifier(address account) external onlyOwner {
revokeRole(CAN_ADD_VERIFIED_USER, account);
}
function addVerifiedUser(address userAddress) external {
require(hasRole(CAN_ADD_VERIFIED_USER, msg.sender), "Caller cannot add verified user");
require(!users[userAddress].isVerified, "Address already verified");
users[userAddress].isVerified = true;
users[userAddress].doublingIndexAtVerification = globalDoublingIndex;
emit VerifiedUserAdded(userAddress);
}
function addGuestUser(address userAddress) external {
require(users[msg.sender].isVerified, "only verified users can invite guests");
require(users[msg.sender].totalSacrificedStablec >= inviteThresholdStablec,
"Need to sacrifice more frax before you can invite others");
require(users[msg.sender].numInvited < maxInvitesPerVerifiedUser,
"Exceed maximum number of invites");
users[userAddress].isGuest = true;
users[msg.sender].numInvited += 1;
}
function mintAndStakeFor(address _staker, uint256 _amountPaidStablec) public whenNotPaused {
User storage userInfo = users[_staker];
if ((block.timestamp - lastUpdatedTimestamp) > SECONDS_IN_DAY) {
globalDoublingIndex *= 2;
lastUpdatedTimestamp += SECONDS_IN_DAY;
}
Factor storage bonusFactor;
if (userInfo.isVerified) {
require(
userInfo.totalSacrificedStablec + _amountPaidStablec <= maxSacrificableStablec(userInfo.doublingIndexAtVerification),
"Exceeded max mint limit");
bonusFactor = verifiedBonusFactor;
} else if (userInfo.isGuest) {
require(userInfo.totalSacrificedStablec + _amountPaidStablec <= limitStablec.guestMax, "Exceeded max mint limit");
bonusFactor = guestBonusFactor;
} else {
revert("Only verified templars and their guests can partake in the opening ceremony");
}
(uint256 _stablec, uint256 _temple) = treasury.intrinsicValueRatio();
uint256 _boughtTemple = _amountPaidStablec * _temple / _stablec / mintMultiple;
uint256 _bonusTemple = _boughtTemple * bonusFactor.numerator / bonusFactor.denominator;
uint256 _totalTemple = _boughtTemple + _bonusTemple;
userInfo.totalSacrificedStablec += _amountPaidStablec;
SafeERC20.safeTransferFrom(stablecToken, msg.sender, address(treasury), _amountPaidStablec);
templeToken.mint(address(this), _totalTemple);
SafeERC20.safeIncreaseAllowance(templeToken, address(staking), _totalTemple);
uint256 _amountOgTemple = staking.stake(_totalTemple);
SafeERC20.safeIncreaseAllowance(staking.OG_TEMPLE(), address(lockedOGTemple), _amountOgTemple);
lockedOGTemple.lockFor(_staker, _amountOgTemple, block.timestamp + unlockDelaySeconds);
if (_amountPaidStablec >= harvestThresholdStablec) {
treasuryManagement.harvest();
}
emit MintComplete(_staker, _amountPaidStablec, _boughtTemple, _bonusTemple, _amountOgTemple);
}
function mintAndStake(uint256 _amountPaidStablec) external whenNotPaused {
mintAndStakeFor(msg.sender, _amountPaidStablec);
}
function stakeFor(address _staker, uint256 _amountTemple) public whenNotPaused {
User storage userInfo = users[_staker];
Factor storage bonusFactor;
if (userInfo.isVerified) {
require(userInfo.totalSacrificedTemple + _amountTemple <= limitTemple.verifiedMax, "exceeded max limit");
bonusFactor = verifiedBonusFactor;
} else if (userInfo.isGuest) {
require(userInfo.totalSacrificedTemple + _amountTemple <= limitTemple.guestMax, "exceeded max limit");
bonusFactor = guestBonusFactor;
} else {
revert("Only verified templars and their guests can partake in the opening ceremony");
}
uint256 _bonusTemple = _amountTemple * bonusFactor.numerator / bonusFactor.denominator;
uint256 _totalTemple = _amountTemple + _bonusTemple;
userInfo.totalSacrificedTemple += _amountTemple;
SafeERC20.safeTransferFrom(templeToken, msg.sender, address(this), _amountTemple);
templeToken.mint(address(this), _bonusTemple);
SafeERC20.safeIncreaseAllowance(templeToken, address(staking), _totalTemple);
uint256 _amountOgTemple = staking.stake(_totalTemple);
SafeERC20.safeIncreaseAllowance(staking.OG_TEMPLE(), address(lockedOGTemple), _amountOgTemple);
lockedOGTemple.lockFor(_staker, _amountOgTemple, block.timestamp + unlockDelaySeconds);
emit StakeComplete(_staker, _amountTemple, _bonusTemple, _amountOgTemple);
}
function stake(uint256 _amountTemple) external whenNotPaused {
stakeFor(msg.sender, _amountTemple);
}
function pause() external onlyOwner {
_pause();
}
function unpause() external onlyOwner {
_unpause();
}
function maxSacrificableStablec(uint256 doublingIndexAtVerification) public view returns(uint256 maxLimit) {
maxLimit = limitStablec.verifiedDayOne * globalDoublingIndex / doublingIndexAtVerification;
if (maxLimit > limitStablec.verifiedMax) {
maxLimit = limitStablec.verifiedMax;
}
}
}
文件 18 的 27:Ownable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() {
_setOwner(_msgSender());
}
function owner() public view virtual returns (address) {
return _owner;
}
modifier onlyOwner() {
require(owner() == _msgSender(), "Ownable: caller is not the owner");
_;
}
function renounceOwnership() public virtual onlyOwner {
_setOwner(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
require(newOwner != address(0), "Ownable: new owner is the zero address");
_setOwner(newOwner);
}
function _setOwner(address newOwner) private {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 19 的 27:Pausable.sol
pragma solidity ^0.8.0;
import "../utils/Context.sol";
abstract contract Pausable is Context {
event Paused(address account);
event Unpaused(address account);
bool private _paused;
constructor() {
_paused = false;
}
function paused() public view virtual returns (bool) {
return _paused;
}
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}
文件 20 的 27:PresaleAllocation.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./TempleERC20Token.sol";
import "./TempleTreasury.sol";
import "./TempleStaking.sol";
contract PresaleAllocation is Ownable {
struct Allocation {
uint256 amount;
uint256 epoch;
}
mapping(address => Allocation) public allocationOf;
function setAllocation(address staker, uint256 amount, uint256 epoch) external onlyOwner {
allocationOf[staker].epoch = epoch;
allocationOf[staker].amount = amount;
}
}
文件 21 的 27:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 22 的 27:SandalwoodToken.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract SandalwoodToken is ERC20, ERC20Burnable {
constructor() ERC20("Sandalwood", "Sandalwood") {
_mint(_msgSender(), 1e12 * 1e18);
}
}
文件 23 的 27:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, 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] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}
文件 24 的 27:TempleERC20Token.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract TempleERC20Token is ERC20, ERC20Burnable, Ownable, AccessControl {
bytes32 public constant CAN_MINT = keccak256("CAN_MINT");
constructor() ERC20("Temple", "TEMPLE") {
_setupRole(DEFAULT_ADMIN_ROLE, owner());
}
function mint(address to, uint256 amount) external {
require(hasRole(CAN_MINT, msg.sender), "Caller cannot mint");
_mint(to, amount);
}
function addMinter(address account) external onlyOwner {
grantRole(CAN_MINT, account);
}
function removeMinter(address account) external onlyOwner {
revokeRole(CAN_MINT, account);
}
}
文件 25 的 27:TempleStaking.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./ABDKMath64x64.sol";
import "./TempleERC20Token.sol";
import "./OGTemple.sol";
import "./ExitQueue.sol";
contract TempleStaking is Ownable {
using ABDKMath64x64 for int128;
TempleERC20Token immutable public TEMPLE;
OGTemple immutable public OG_TEMPLE;
ExitQueue public EXIT_QUEUE;
int128 public epy;
uint256 public epochSizeSeconds;
uint256 public startTimestamp;
int128 public accumulationFactor;
uint256 public lastUpdatedEpoch;
event StakeCompleted(address _staker, uint256 _amount, uint256 _lockedUntil);
event AccumulationFactorUpdated(uint256 _epochsProcessed, uint256 _currentEpoch, uint256 _accumulationFactor);
event UnstakeCompleted(address _staker, uint256 _amount);
constructor(
TempleERC20Token _TEMPLE,
ExitQueue _EXIT_QUEUE,
uint256 _epochSizeSeconds,
uint256 _startTimestamp) {
require(_startTimestamp < block.timestamp, "Start timestamp must be in the past");
require(_startTimestamp > (block.timestamp - (24 * 2 * 60 * 60)), "Start timestamp can't be more than 2 days in the past");
TEMPLE = _TEMPLE;
EXIT_QUEUE = _EXIT_QUEUE;
OG_TEMPLE = new OGTemple();
epochSizeSeconds = _epochSizeSeconds;
startTimestamp = _startTimestamp;
epy = ABDKMath64x64.fromUInt(1);
accumulationFactor = ABDKMath64x64.fromUInt(1);
}
function setExitQueue(ExitQueue _EXIT_QUEUE) external onlyOwner {
EXIT_QUEUE = _EXIT_QUEUE;
}
function setEpy(uint256 _numerator, uint256 _denominator) external onlyOwner {
_updateAccumulationFactor();
epy = ABDKMath64x64.fromUInt(1).add(ABDKMath64x64.divu(_numerator, _denominator));
}
function getEpy(uint256 _scale) external view returns (uint256) {
return epy.sub(ABDKMath64x64.fromUInt(1)).mul(ABDKMath64x64.fromUInt(_scale)).toUInt();
}
function currentEpoch() public view returns (uint256) {
return (block.timestamp - startTimestamp) / epochSizeSeconds;
}
function getAccumulationFactor(uint256 _scale) external view returns(uint256) {
return _accumulationFactorAt(currentEpoch()).mul(ABDKMath64x64.fromUInt(_scale)).toUInt();
}
function _accumulationFactorAt(uint256 epoch) private view returns(int128) {
uint256 _nUnupdatedEpochs = epoch - lastUpdatedEpoch;
return accumulationFactor.mul(epy.pow(_nUnupdatedEpochs));
}
function balance(uint256 amountOgTemple) public view returns(uint256) {
return _overflowSafeMul1e18(
ABDKMath64x64.divu(amountOgTemple, 1e18).mul(_accumulationFactorAt(currentEpoch()))
);
}
function _updateAccumulationFactor() internal {
uint256 _currentEpoch = currentEpoch();
if (_currentEpoch <= lastUpdatedEpoch) {
return;
}
accumulationFactor = _accumulationFactorAt(_currentEpoch);
lastUpdatedEpoch = _currentEpoch;
uint256 _nUnupdatedEpochs = _currentEpoch - lastUpdatedEpoch;
emit AccumulationFactorUpdated(_nUnupdatedEpochs, _currentEpoch, accumulationFactor.mul(10000).toUInt());
}
function stakeFor(address _staker, uint256 _amountTemple) public returns(uint256 amountOgTemple) {
require(_amountTemple > 0, "Cannot stake 0 tokens");
_updateAccumulationFactor();
amountOgTemple = _overflowSafeMul1e18(ABDKMath64x64.divu(_amountTemple, 1e18).div(accumulationFactor));
SafeERC20.safeTransferFrom(TEMPLE, msg.sender, address(this), _amountTemple);
OG_TEMPLE.mint(_staker, amountOgTemple);
emit StakeCompleted(_staker, _amountTemple, 0);
return amountOgTemple;
}
function stake(uint256 _amountTemple) external returns(uint256 amountOgTemple) {
return stakeFor(msg.sender, _amountTemple);
}
function unstake(uint256 _amountOgTemple) external {
require(OG_TEMPLE.allowance(msg.sender, address(this)) >= _amountOgTemple, 'Insufficient OGTemple allowance. Cannot unstake');
_updateAccumulationFactor();
uint256 unstakeBalanceTemple = balance(_amountOgTemple);
OG_TEMPLE.burnFrom(msg.sender, _amountOgTemple);
SafeERC20.safeIncreaseAllowance(TEMPLE, address(EXIT_QUEUE), unstakeBalanceTemple);
EXIT_QUEUE.join(msg.sender, unstakeBalanceTemple);
emit UnstakeCompleted(msg.sender, _amountOgTemple);
}
function _overflowSafeMul1e18(int128 amountFixedPoint) internal pure returns (uint256) {
uint256 integralDigits = amountFixedPoint.toUInt();
uint256 fractionalDigits = amountFixedPoint.sub(ABDKMath64x64.fromUInt(integralDigits)).mul(ABDKMath64x64.fromUInt(1e18)).toUInt();
return (integralDigits * 1e18) + fractionalDigits;
}
}
文件 26 的 27:TempleTreasury.sol
pragma solidity ^0.8.4;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/security/Pausable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./TempleERC20Token.sol";
import "./ITreasuryAllocation.sol";
import "./MintAllowance.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
contract TempleTreasury is Ownable {
TempleERC20Token private TEMPLE;
IERC20 private STABLEC;
MintAllowance public MINT_ALLOWANCE;
struct IntrinsicValueRatio {
uint256 stablec;
uint256 temple;
}
IntrinsicValueRatio public intrinsicValueRatio;
uint256 public harvestedRewardsTemple;
bool public seeded = false;
address[] public pools;
mapping(address => uint96) public poolHarvestShare;
uint96 public totalHarvestShares;
mapping(ITreasuryAllocation => uint256) public treasuryAllocationsStablec;
uint256 public totalAllocationStablec;
event RewardsHarvested(uint256 _amount);
event HarvestDistributed(address _contract, uint256 _amount);
constructor(TempleERC20Token _TEMPLE, IERC20 _STABLEC) {
TEMPLE = _TEMPLE;
STABLEC = _STABLEC;
MINT_ALLOWANCE = new MintAllowance(_TEMPLE);
}
function numPools() external view returns (uint256) {
return pools.length;
}
function seedMint(uint256 amountStablec, uint256 amountTemple) external onlyOwner {
require(!seeded, "Owner has already seeded treasury");
seeded = true;
intrinsicValueRatio.stablec = amountStablec;
intrinsicValueRatio.temple = amountTemple;
SafeERC20.safeTransferFrom(STABLEC, msg.sender, address(this), amountStablec);
TEMPLE.mint(msg.sender, amountTemple);
}
function harvest(uint256 distributionPercent) external onlyOwner {
require(distributionPercent <= 100, "Scaling factor interpreted as a %, needs to be between 0 (no harvest) and 100 (max harvest)");
uint256 reserveStablec = STABLEC.balanceOf(address(this)) + totalAllocationStablec;
if (TEMPLE.balanceOf(address(this)) > harvestedRewardsTemple) {
TEMPLE.burn(TEMPLE.balanceOf(address(this)) - harvestedRewardsTemple);
}
uint256 totalSupplyTemple = TEMPLE.totalSupply() - TEMPLE.balanceOf(address(MINT_ALLOWANCE));
uint256 impliedSupplyAtCurrentIVTemple = reserveStablec * intrinsicValueRatio.temple / intrinsicValueRatio.stablec;
require(impliedSupplyAtCurrentIVTemple >= totalSupplyTemple, "Cannot run harvest when IV drops");
uint256 newHarvestTemple = (impliedSupplyAtCurrentIVTemple - totalSupplyTemple) * distributionPercent / 100;
harvestedRewardsTemple += newHarvestTemple;
intrinsicValueRatio.stablec = reserveStablec;
intrinsicValueRatio.temple = totalSupplyTemple + newHarvestTemple;
TEMPLE.mint(address(this), newHarvestTemple);
emit RewardsHarvested(newHarvestTemple);
}
function resetIV() external onlyOwner {
uint256 reserveStablec = STABLEC.balanceOf(address(this)) + totalAllocationStablec;
uint256 totalSupplyTemple = TEMPLE.totalSupply() - TEMPLE.balanceOf(address(MINT_ALLOWANCE));
intrinsicValueRatio.stablec = reserveStablec;
intrinsicValueRatio.temple = totalSupplyTemple;
}
function distributeHarvest() external onlyOwner {
uint256 totalAllocated = 0;
for (uint256 i = 0; i < pools.length; i++) {
uint256 allocatedRewards = harvestedRewardsTemple * poolHarvestShare[pools[i]] / totalHarvestShares;
if ((totalAllocated + allocatedRewards) > harvestedRewardsTemple) {
allocatedRewards = harvestedRewardsTemple - totalAllocated;
}
totalAllocated += allocatedRewards;
SafeERC20.safeTransfer(TEMPLE, pools[i], allocatedRewards);
emit HarvestDistributed(pools[i], allocatedRewards);
}
harvestedRewardsTemple -= totalAllocated;
}
function mintAndAllocateTemple(address _contract, uint256 amountTemple) external onlyOwner {
require(amountTemple > 0, "TEMPLE to mint and allocate must be > 0");
TEMPLE.mint(address(this), amountTemple);
SafeERC20.safeIncreaseAllowance(TEMPLE, address(MINT_ALLOWANCE), amountTemple);
MINT_ALLOWANCE.increaseMintAllowance(_contract, amountTemple);
}
function unallocateAndBurnUnusedMintedTemple(address _contract) external onlyOwner {
MINT_ALLOWANCE.burnUnusedMintAllowance(_contract);
}
function allocateTreasuryStablec(ITreasuryAllocation _contract, uint256 amountStablec) external onlyOwner {
require(amountStablec > 0, "STABLEC to allocate must be > 0");
treasuryAllocationsStablec[_contract] += amountStablec;
totalAllocationStablec += amountStablec;
SafeERC20.safeTransfer(STABLEC, address(_contract), amountStablec);
}
function updateMarkToMarket(ITreasuryAllocation _contract) external onlyOwner {
uint256 oldReval = treasuryAllocationsStablec[_contract];
uint256 newReval = _contract.reval();
totalAllocationStablec = totalAllocationStablec + newReval - oldReval;
treasuryAllocationsStablec[_contract] = newReval;
}
function withdraw(ITreasuryAllocation _contract) external onlyOwner {
uint256 preWithdrawlReval = _contract.reval();
uint256 pendingWithdrawal = STABLEC.allowance(address(_contract), address(this));
SafeERC20.safeTransferFrom(STABLEC, address(_contract), address(this), pendingWithdrawal);
uint256 postWithdrawlReval = _contract.reval();
totalAllocationStablec = totalAllocationStablec - pendingWithdrawal;
treasuryAllocationsStablec[_contract] -= pendingWithdrawal;
require(postWithdrawlReval + pendingWithdrawal == preWithdrawlReval);
}
function ejectTreasuryAllocation(ITreasuryAllocation _contract) external onlyOwner {
uint256 pendingWithdrawal = STABLEC.allowance(address(_contract), address(this));
totalAllocationStablec -= treasuryAllocationsStablec[_contract];
treasuryAllocationsStablec[_contract] = 0;
SafeERC20.safeTransferFrom(STABLEC, address(_contract), address(this), pendingWithdrawal);
}
function upsertPool(address _contract, uint96 _poolHarvestShare) external onlyOwner {
require(_poolHarvestShare > 0, "Harvest share must be > 0");
totalHarvestShares = totalHarvestShares + _poolHarvestShare - poolHarvestShare[_contract];
if (poolHarvestShare[_contract] == 0) {
pools.push(_contract);
}
poolHarvestShare[_contract] = _poolHarvestShare;
}
function removePool(uint256 idx, address _contract) external onlyOwner {
require(idx < pools.length, "No pool at the specified index");
require(pools[idx] == _contract, "Pool at index and passed in address don't match");
pools[idx] = pools[pools.length-1];
pools.pop();
totalHarvestShares -= poolHarvestShare[_contract];
delete poolHarvestShare[_contract];
}
}
文件 27 的 27:TreasuryManagementProxy.sol
pragma solidity ^0.8.4;
import "./TempleTreasury.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
contract TreasuryManagementProxy {
TempleTreasury public treasury;
bool public harvestEnabled = true;
address owner;
uint256 public harvestDistributionPercentage = 80;
constructor(address _owner, address _treasury) {
owner = _owner;
treasury = TempleTreasury(_treasury);
}
modifier onlyOwner() {
require(owner == msg.sender, "caller is not the owner");
_;
}
function harvest() external {
if (harvestEnabled) {
treasury.harvest(harvestDistributionPercentage);
}
}
function setHarvestDistributionPercentage(uint256 _harvestDistributionPercentage) external onlyOwner {
harvestDistributionPercentage = _harvestDistributionPercentage;
}
function toggleHarvest() external onlyOwner {
harvestEnabled = !harvestEnabled;
}
function resetIV() external onlyOwner {
treasury.resetIV();
}
function distributeHarvest() external onlyOwner {
treasury.distributeHarvest();
}
function mintAndAllocateTemple(address _contract, uint256 amountTemple) external onlyOwner {
treasury.mintAndAllocateTemple(_contract, amountTemple);
}
function unallocateAndBurnUnusedMintedTemple(address _contract) external onlyOwner {
treasury.unallocateAndBurnUnusedMintedTemple(_contract);
}
function allocateTreasuryStablec(ITreasuryAllocation _contract, uint256 amountStablec) external onlyOwner {
treasury.allocateTreasuryStablec(_contract, amountStablec);
}
function updateMarkToMarket(ITreasuryAllocation _contract) external onlyOwner {
treasury.updateMarkToMarket(_contract);
}
function withdraw(ITreasuryAllocation _contract) external onlyOwner {
treasury.withdraw(_contract);
}
function ejectTreasuryAllocation(ITreasuryAllocation _contract) external onlyOwner {
treasury.ejectTreasuryAllocation(_contract);
}
function upsertPool(address _contract, uint96 _poolHarvestShare) external onlyOwner {
treasury.upsertPool(_contract, _poolHarvestShare);
}
function removePool(uint256 idx, address _contract) external onlyOwner {
treasury.removePool(idx, _contract);
}
function transferOwnership(address newOwner) external onlyOwner {
treasury.transferOwnership(newOwner);
}
}
{
"compilationTarget": {
"contracts/OpeningCeremony.sol": "OpeningCeremony"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"contract IERC20","name":"_stablecToken","type":"address"},{"internalType":"contract TempleERC20Token","name":"_templeToken","type":"address"},{"internalType":"contract TempleStaking","name":"_staking","type":"address"},{"internalType":"contract LockedOGTemple","name":"_lockedOGTemple","type":"address"},{"internalType":"contract TempleTreasury","name":"_treasury","type":"address"},{"internalType":"contract TreasuryManagementProxy","name":"_treasuryManagement","type":"address"},{"internalType":"uint256","name":"_harvestThresholdStablec","type":"uint256"},{"internalType":"uint256","name":"_inviteThresholdStablec","type":"uint256"},{"internalType":"uint256","name":"_maxInvitesPerVerifiedUser","type":"uint256"},{"components":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"internalType":"struct OpeningCeremony.Factor","name":"_verifiedBonusFactor","type":"tuple"},{"components":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"internalType":"struct OpeningCeremony.Factor","name":"_guestBonusFactor","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"acceptedStablec","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintedTemple","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonusTemple","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintedOGTemple","type":"uint256"}],"name":"MintComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"staker","type":"address"},{"indexed":false,"internalType":"uint256","name":"acceptedTemple","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bonusTemple","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"mintedOGTemple","type":"uint256"}],"name":"StakeComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"user","type":"address"}],"name":"VerifiedUserAdded","type":"event"},{"inputs":[],"name":"CAN_ADD_VERIFIED_USER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"addGuestUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"userAddress","type":"address"}],"name":"addVerifiedUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalDoublingIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"guestBonusFactor","outputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvestThresholdStablec","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"inviteThresholdStablec","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastUpdatedTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitStablec","outputs":[{"internalType":"uint256","name":"guestMax","type":"uint256"},{"internalType":"uint256","name":"verifiedMax","type":"uint256"},{"internalType":"uint256","name":"verifiedDayOne","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"limitTemple","outputs":[{"internalType":"uint256","name":"guestMax","type":"uint256"},{"internalType":"uint256","name":"verifiedMax","type":"uint256"},{"internalType":"uint256","name":"verifiedDayOne","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lockedOGTemple","outputs":[{"internalType":"contract LockedOGTemple","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxInvitesPerVerifiedUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"doublingIndexAtVerification","type":"uint256"}],"name":"maxSacrificableStablec","outputs":[{"internalType":"uint256","name":"maxLimit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountPaidStablec","type":"uint256"}],"name":"mintAndStake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_amountPaidStablec","type":"uint256"}],"name":"mintAndStakeFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"mintMultiple","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removeVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numerator","type":"uint256"},{"internalType":"uint256","name":"_denominator","type":"uint256"}],"name":"setGuestBonusFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_harvestThresholdStablec","type":"uint256"}],"name":"setHarvestThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_inviteThresholdStablec","type":"uint256"}],"name":"setInviteThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"guestMax","type":"uint256"},{"internalType":"uint256","name":"verifiedMax","type":"uint256"},{"internalType":"uint256","name":"verifiedDayOne","type":"uint256"}],"name":"setLimitStablec","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"guestMax","type":"uint256"},{"internalType":"uint256","name":"verifiedMax","type":"uint256"}],"name":"setLimitTemple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_maxInvitesPerVerifiedUser","type":"uint256"}],"name":"setMaxInvitesPerVerifiedUser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintMultiple","type":"uint256"}],"name":"setMintMultiple","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_unlockDelaySeconds","type":"uint256"}],"name":"setUnlockDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numerator","type":"uint256"},{"internalType":"uint256","name":"_denominator","type":"uint256"}],"name":"setVerifiedBonusFactor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stablecToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amountTemple","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_staker","type":"address"},{"internalType":"uint256","name":"_amountTemple","type":"uint256"}],"name":"stakeFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"staking","outputs":[{"internalType":"contract TempleStaking","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"templeToken","outputs":[{"internalType":"contract TempleERC20Token","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"contract TempleTreasury","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"treasuryManagement","outputs":[{"internalType":"contract TreasuryManagementProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unlockDelaySeconds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"users","outputs":[{"internalType":"bool","name":"isVerified","type":"bool"},{"internalType":"bool","name":"isGuest","type":"bool"},{"internalType":"uint8","name":"numInvited","type":"uint8"},{"internalType":"uint256","name":"doublingIndexAtVerification","type":"uint256"},{"internalType":"uint256","name":"totalSacrificedStablec","type":"uint256"},{"internalType":"uint256","name":"totalSacrificedTemple","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifiedBonusFactor","outputs":[{"internalType":"uint256","name":"numerator","type":"uint256"},{"internalType":"uint256","name":"denominator","type":"uint256"}],"stateMutability":"view","type":"function"}]