Transaction Hash:
Block:
11020730 at Oct-09-2020 10:38:54 AM +UTC
Transaction Fee:
0.34613628 ETH
$655.35
Gas Used:
2,884,469 Gas / 120 Gwei
Emitted Events:
5 |
Mooniswap.OwnershipTransferred( previousOwner=0x00000000...000000000, newOwner=[Receiver] MooniFactory )
|
6 |
Mooniswap.OwnershipTransferred( previousOwner=[Receiver] MooniFactory, newOwner=0x68a17B58...3A46De6b5 )
|
7 |
MooniFactory.Deployed( mooniswap=Mooniswap, token1=0x00000000...000000000, token2=VotingToken )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x3Ed2654C...9D369c027 |
49.89024787537762405 Eth
Nonce: 378
|
49.54411159537762405 Eth
Nonce: 379
| 0.34613628 | ||
0x5A0b54D5...D3E029c4c
Miner
| (Spark Pool) | 21.685018705975877847 Eth | 22.031154985975877847 Eth | 0.34613628 | |
0x71CD6666...D3ee7D303 | |||||
0xAa5Bac68...4a2984ae5 |
0 Eth
Nonce: 0
|
0 Eth
Nonce: 1
|
Execution Trace
MooniFactory.deploy( tokenA=0x0000000000000000000000000000000000000000, tokenB=0x9E78b8274e1D6a76a0dBbf90418894DF27cBCEb5 ) => ( pool=0xAa5Bac68C9C655FE7779030031A79084a2984ae5 )
-
VotingToken.STATICCALL( )
-
Mooniswap.60806040( )
-
Mooniswap.transferOwnership( newOwner=0x68a17B587CAF4f9329f0e372e3A78D23A46De6b5 )
deploy[MooniFactory (ln:1505)]
sortTokens[MooniFactory (ln:1509)]
uniSymbol[MooniFactory (ln:1514)]
uniSymbol[MooniFactory (ln:1515)]
transferOwnership[MooniFactory (ln:1523)]
owner[MooniFactory (ln:1523)]
push[MooniFactory (ln:1526)]
Deployed[MooniFactory (ln:1529)]
File 1 of 3: MooniFactory
File 2 of 3: Mooniswap
File 3 of 3: VotingToken
/* MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXK0OxdoollccccclodkOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0kdlc;'.. .,:loxkk0KXNWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKkoc,.. .':ox0XNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOd:'. .;lxKNWMMMMMMMMMMMMMMMWWNNNNNNNNWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo:. .,lkXWMMMMMMMMMWXKOxddol:;;,''.....'',,;:cldxO0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXxc' .;d0NMMMMMMMWXOxl:,.. ..,:ldOKNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXx:. .;dKWMMMMMWN0dc,. .,cdOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNkc. 'l0NMMMMMN0d:'. .:d0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMW0o' .;xXMMMMMNOo,. .....''',,'''.... .'lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMNOc. .:kNMMMMW0o, ..,:loxk0KKXXNNNWWWNNNNXKK0kxol:,.. .cONMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMNk;. .;ONMMMMXx;. .,cdkKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOdc;. ,oKWMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMNk; ,kNMMMW0l. ':dOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOd:' .cOWMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMWO: .dXMMMW0c. .;oONWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .:ONMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMWKc. :0WMMWKl. .;dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNWMMMMMMMMMMWKx:. .:OWMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMNx. .dNMMMXd. ,o0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0kxOXWMMMMMMMMWKd;. .cKWMMMMMMMMMMMMMMM MMMMMMMMMMMMMMW0: ,OWMMWO, .:kNMMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMWXxc,:d0NMMMMMMMMNOc. .xNMMMMMMMMMMMMMM MMMMMMMMMMMMMNx. :KMMMXo..c0WMMMMMMMMMMMMMMMMMMMMXxl:;,;;:codkKNMMMMMMMMMMMMMMMMMMMMMMNk;..,o0WMMMMMMMWKo. :KMMMMMMMMMMMMM MMMMMMMMMMMMXl. cXMMW0:.c0WMMMMMMMMMMMMWWNNXXXNNWXd'..;;'.. .,lkNMMW00NMMMMMMMMMMMMMMMNk; .;dKWMMMMMMWKo. 'kWMMMMMMMMMMM MMMMMMMMMMMK: cXMMWk;;OWMMMMMMMMMN0xoc;,'.....';cll'.oKNX0xol, ,xXNc.,xXMMMMMMMMMMMMMMMNx' .l0WMMMMMMWKl. .dNMMMMMMMMMM MMMMMMMMMM0; cXMMWk:dXMMMMMMMMW0o,. ..,:clllllcc:;,..;0WMMMMNO:. ;Ol. ;0MMMMMMMMMMMMMMMMXl. .:OWMMMMMMWO; .lNMMMMMMMMM MMMMMMMMM0, ;KMMWklkNWMMMMMMMKl. .';coxOXWMMMMWNKOdxKWMMMMMWk, .:l: ,0MMMMMMMMMMMMMMMMWO, .c0WMMMMMMXo. lXMMMMMMMM MMMMMMMM0, '0MMNx,''lXMMMMMWk' .,cdxkkkxdxxOKXWMMMMMMWNXNMMMMMM0, .kK; cNMMMMMMN0XMMMMMMMMKc .oXMMMMMMWO, lNMMMMMMM MMMMMMM0; .xWMKc. . .kWMMMNd. .l0NMMMMMMMMMMWNXNWMMMMMMMWNNWMMMMMk. 'OWd. .OMMMMXx:oXMMMMMMMMMNo. ,kWMMMMMMK: .dWMMMMMM MMMMMMX: cXM0; .l0o..:ool, .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMX; ;XMO. .dWWKo'.:KMMMMMMMMMMMWx. .oXMMMMMMXc .kWMMMMM MMMMMNl .OMX: .oNMWOc'...':dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNc.dWMO. lOl. ,0MMMMMMMMMMMMMWx. :KMMMMMMXl ;KMMMMM MMMMWx. lNMx. ;XMMMMMNXKXNWMWNWMMMMMMMMMMMMMMMXO0WMMMMMMMMMMMMMMMK::XMWx. ...'.'OMMMMMMMMMMMMMMMWd. ;0MMMMMMXc oWMMMM MMMMK, .kMNl cNMMMMMMMWNX0kxONMMMMMMMMMMMMMMWd..,cok0NWMMMMMMMMM0xKMMX; .cd;'kWMMMMMMMMMMMMMMMMNo ,0MMMMMMK: '0MMMM MMMWo .cl:. .,ooolllllc::ld0WMMMMMMMMMMMMMMMNl .':oOXNMMMMMWMMWO: ;d00:.xWMMMMMMMMMMMMMMMMMMX: ;KMMMMMM0' oWMMM MMM0' .':ok0KKK0OkxxkOKNWMMMMMMMMMMMMMMMMMMWo ..;OWMMMMWO:. ,OWK:.dWMMMMMMMMMMMMMMMMMMMMO' :XMMMMMWd. ,KMMM MMWo .l0NWMMMMMMMMMMMMMMMMMMMMMMMMWXKWMMMMW0o' .kWMWO:. .cOOOO:.oNMMMMMMMMMNXWMMMMMMMMMWo .oWMMMMMX: .kMMM MMK, .OMMMMMMMMMMMMMMMMMMMMMMMMN0d:.cXMMMKc. .ok:. ..;KMMX:.lNMMMMMMMMMWxlKMMMMMMMMMM0, 'OMMMMMWk. oWMM MMx. 'OXXNMMMMMMMMMMMMMMMMMWXkl,. lWMWO' ,O0dd0Kc .kMMMMMMMMMWk' cXMMMMMMMMMWl lNMMMMMX; cNMM MNl .dOKNMMMMMMMMMMMMMMWKxc. lWM0, 'xXWN0: ;0MMMWN0xl,. 'cdOXWMMMMMk. 'OMMMMMWd. ;XMM MX; ;XMMMMMMMMNOkXMMWKx;. ,KWo .:c, ;KMMWN0ko;. 'cdOXWMMMMMK, dWMMMMMO. ,KMM M0' ,KMMMMXKN0:.oWW0c. ;d; lNMMMMMMWO'.dNMMMMMMMMMMNc :XMMMMMK, ;KMM MO. '0MMM0lkO, 'ONd. .oNMMMMMMWkdNMMMMMMMMMMMWo ,KMMMMMX: ;XMM Mk. .OMM0,,x; ;Ol ..',. ;KMMMMMMMNNMMMMMMMMMMMMWo '0MMMMMNc cNMM Mx. .dW0, ,:. ,c. .:0Xk:. lNMMMMMMMMMMMMMMMMMMMMMWo .OMMMMMNc oWMM Mk. c0: .. . .,xOd0NO; '0MMMMMMMMMMMMMWWMMMMMMMWo .OMMMMMN: .kMMM Mk. .:. .,. .cx: .lKXl lWMMMMMMMMMMMWNxlONMMMMMNc '0MMMMMX; ;XMMM M0' .:c. .. .,:;,,l0Xl .xMMMMMMMMMMMWNk,.:ONMMMMX; ;XMMMMM0' .dWMMM MK; 'dl. .....''',:k0d;. oWMMMMMMMMMMMMWOo0MMMMMMO. oWMMMMMx. ,KMMMM MNc :kl. ...... ,c;. :XMMMMMMMMMMMMMWWWMMMMMWo .kMMMMMNc .dWMMMM MWd. c0l. .OMMMMMMMMMMMMMMMMMMMMMK; :XMMMMMO' :XMMMMM MM0' :0d. . lNMMMMMMMMMMMMMMMMMMMWd. .kMMMMMNl '0MMMMMM MMNl '0k. .. 'c. .OMMMMMMMMMMMMMMMMMMM0, lNMMMMMO. .kWMMMMMM MMMO. .dK; ;0O; :d' ;KMMMMMMMMMMMMMMMMMNl ,KMMMMMX: .xWMMMWXNM MMMNc ,0d. .OMMNk:. .x0xo, cXMMMMMMMMMMMMMMMWd. 'OMMMMMNo .dWMMMWOkNM MMMMO' c0; .dWMMMMW0l. ;dooxl. :0WMMMMMMMMMMMMWk. .kWMMMMWx. .xWMMMWxc0MM MMMMWd. ok. :XMMMMMMMWO, .:dc 'OWMMMMMMMMMMWO' .kWMMMMWk. 'kWMMMNo,dWMM MMMMMX: cd. .kWMMMMMMMMWk. .. .,cc. :XMMMMMMMMMWk' 'OWMMMMWk. :0MMMMKc.cXMMM MMMMMM0, .'. :XMMMMMMMMMMNc 'c;ll. .. .OMMMMMMMMWx. :KMMMMMNx. .oNMMMWO, ;KMMMM MMMMMMWO' .xWMMMMMMMMMMMk:. ,0KOOc .OMMMMMMMNo. .oXMMMMMXo. ;OWMMMXl. 'OMMMMM MMMMMMMWk. ,0MMMMMMMMMMMMX0: .:d00l. lNMMMMMW0: ;OWMMMMW0: 'xNMMMNk, 'OWMMMMM MMMMMMMMWx. :XMMMMMNNMMMMMMWk. .',. 'xNMMMMMNx. ,xNMMMMMNx. .oXMMMWO:. 'OWMMMMMM MMMMMMMMMWk. cNMMMMNdxNMMMMMMWO:. .;xXMMMMMWO: 'dXMMMMMWO; .oKWMMW0c. 'OWMMMMMMM MMMMMMMMMMWO, cNWNKk:..:kKNWMMMMWKxc'. .,oONMMMMMW0c. .;xXMMMMMWKl..,dXWMMNOc. ;0WMMMMMMMM MMMMMMMMMMMMK: cNWN0o' 'oONWMMMMMMMWN0dc;''';lxKNMMMMMMW0l. .cONMMMMMWKl'.ckNMMMNk;. cKMMMMMMMMMM MMMMMMMMMMMMMXo. cNMMMMKccKMMMMMMMMMMMMMMMMWNNNWMMMMMMMMNOc. .:xXWMMMMMWOl;:dKWMMW0o' .dNMMMMMMMMMMM MMMMMMMMMMMMMMWk' lNMMMMMXXMMMMMMMMMMMMMMMMMMMMMMMMMMMWKx;. .,lkXWMMMMMWXOdoxKWMMWKd;. ;OWMMMMMMMMMMMM MMMMMMMMMMMMMMMMKl. oWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXkc,';lxKNMMMMMMMWX0OOXWMMN0d;. .oXMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMWk; lXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOxdxOXWMMMMMMMMMMMWNWMMWKxl,. .:0WMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMXd' .:ok0NWMMMMMMMMMMMMMMMMMMMMMMMWNWWMMMMMMMMMMMMMMMMWX0xl,. ,kNMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMXo. .':ldOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXKOdc;.. 'xNMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMWKo' .';ccldxO0KXXNWWWWWWWWWNNXKKOkxol:,.. ,xXMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMWXd, ....',,,,,,,,,'.... .;kNMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMNk:. .l0WMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo,. .:xXWMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo, .;dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .:xKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKxc'. .;oOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0xl;. .':oOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOdl;'. ..,cokKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOxoc;,... ..';:ldk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWXK0Okxdollcccc:::cccclloddkO0KXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ███╗ ███╗ ██████╗ ██████╗ ███╗ ██╗██╗███████╗██╗ ██╗ █████╗ ██████╗ ███████╗██╗ ██╗ ██████╗██╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗ ████╗ ████║██╔═══██╗██╔═══██╗████╗ ██║██║██╔════╝██║ ██║██╔══██╗██╔══██╗██╔════╝╚██╗██╔╝██╔════╝██║ ██║██╔══██╗████╗ ██║██╔════╝ ██╔════╝ ██╔████╔██║██║ ██║██║ ██║██╔██╗ ██║██║███████╗██║ █╗ ██║███████║██████╔╝█████╗ ╚███╔╝ ██║ ███████║███████║██╔██╗ ██║██║ ███╗█████╗ ██║╚██╔╝██║██║ ██║██║ ██║██║╚██╗██║██║╚════██║██║███╗██║██╔══██║██╔═══╝ ██╔══╝ ██╔██╗ ██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║██╔══╝ ██║ ╚═╝ ██║╚██████╔╝╚██████╔╝██║ ╚████║██║███████║╚███╔███╔╝██║ ██║██║██╗ ███████╗██╔╝ ██╗╚██████╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ██████╗ ██╗ ██╗ ██╗██╗███╗ ██╗ ██████╗██╗ ██╗ ██╔══██╗╚██╗ ██╔╝ ███║██║████╗ ██║██╔════╝██║ ██║ ██████╔╝ ╚████╔╝ ╚██║██║██╔██╗ ██║██║ ███████║ ██╔══██╗ ╚██╔╝ ██║██║██║╚██╗██║██║ ██╔══██║ ██████╔╝ ██║ ██║██║██║ ╚████║╚██████╗██║ ██║ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝╚═╝ ╚═╝ */ // File: @openzeppelin/contracts/GSN/Context.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/access/Ownable.sol pragma solidity ^0.6.0; /** * @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. */ 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 () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = 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"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: @openzeppelin/contracts/math/SafeMath.sol pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts/utils/Address.sol pragma solidity ^0.6.2; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * 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 functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.6.0; /** * @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 SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @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' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. 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"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/libraries/UniERC20.sol pragma solidity ^0.6.0; library UniERC20 { using SafeMath for uint256; using SafeERC20 for IERC20; function isETH(IERC20 token) internal pure returns(bool) { return (address(token) == address(0)); } function uniBalanceOf(IERC20 token, address account) internal view returns (uint256) { if (isETH(token)) { return account.balance; } else { return token.balanceOf(account); } } function uniTransfer(IERC20 token, address payable to, uint256 amount) internal { if (amount > 0) { if (isETH(token)) { to.transfer(amount); } else { token.safeTransfer(to, amount); } } } function uniTransferFromSenderToThis(IERC20 token, uint256 amount) internal { if (amount > 0) { if (isETH(token)) { require(msg.value >= amount, "UniERC20: not enough value"); if (msg.value > amount) { // Return remainder if exist msg.sender.transfer(msg.value.sub(amount)); } } else { token.safeTransferFrom(msg.sender, address(this), amount); } } } function uniSymbol(IERC20 token) internal view returns(string memory) { if (isETH(token)) { return "ETH"; } (bool success, bytes memory data) = address(token).staticcall{ gas: 20000 }( abi.encodeWithSignature("symbol()") ); if (!success) { (success, data) = address(token).staticcall{ gas: 20000 }( abi.encodeWithSignature("SYMBOL()") ); } if (success && data.length >= 96) { (uint256 offset, uint256 len) = abi.decode(data, (uint256, uint256)); if (offset == 0x20 && len > 0 && len <= 256) { return string(abi.decode(data, (bytes))); } } if (success && data.length == 32) { uint len = 0; while (len < data.length && data[len] >= 0x20 && data[len] <= 0x7E) { len++; } if (len > 0) { bytes memory result = new bytes(len); for (uint i = 0; i < len; i++) { result[i] = data[i]; } return string(result); } } return _toHex(address(token)); } function _toHex(address account) private pure returns(string memory) { return _toHex(abi.encodePacked(account)); } function _toHex(bytes memory data) private pure returns(string memory) { bytes memory str = new bytes(2 + data.length * 2); str[0] = "0"; str[1] = "x"; uint j = 2; for (uint i = 0; i < data.length; i++) { uint a = uint8(data[i]) >> 4; uint b = uint8(data[i]) & 0x0f; str[j++] = byte(uint8(a + 48 + (a/10)*39)); str[j++] = byte(uint8(b + 48 + (b/10)*39)); } return string(str); } } // File: @openzeppelin/contracts/utils/ReentrancyGuard.sol pragma solidity ^0.6.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File: @openzeppelin/contracts/math/Math.sol pragma solidity ^0.6.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @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, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol pragma solidity ^0.6.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; using Address for address; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File: contracts/libraries/Sqrt.sol pragma solidity ^0.6.0; library Sqrt { // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint256 y) internal pure returns (uint256) { if (y > 3) { uint256 z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } return z; } else if (y != 0) { return 1; } else { return 0; } } } // File: contracts/Mooniswap.sol pragma solidity ^0.6.0; interface IFactory { function fee() external view returns(uint256); } library VirtualBalance { using SafeMath for uint256; struct Data { uint216 balance; uint40 time; } uint256 public constant DECAY_PERIOD = 5 minutes; function set(VirtualBalance.Data storage self, uint256 balance) internal { self.balance = uint216(balance); self.time = uint40(block.timestamp); } function update(VirtualBalance.Data storage self, uint256 realBalance) internal { set(self, current(self, realBalance)); } function scale(VirtualBalance.Data storage self, uint256 realBalance, uint256 num, uint256 denom) internal { set(self, current(self, realBalance).mul(num).add(denom.sub(1)).div(denom)); } function current(VirtualBalance.Data memory self, uint256 realBalance) internal view returns(uint256) { uint256 timePassed = Math.min(DECAY_PERIOD, block.timestamp.sub(self.time)); uint256 timeRemain = DECAY_PERIOD.sub(timePassed); return uint256(self.balance).mul(timeRemain).add( realBalance.mul(timePassed) ).div(DECAY_PERIOD); } } contract Mooniswap is ERC20, ReentrancyGuard, Ownable { using Sqrt for uint256; using SafeMath for uint256; using UniERC20 for IERC20; using VirtualBalance for VirtualBalance.Data; struct Balances { uint256 src; uint256 dst; } struct SwapVolumes { uint128 confirmed; uint128 result; } event Deposited( address indexed account, uint256 amount ); event Withdrawn( address indexed account, uint256 amount ); event Swapped( address indexed account, address indexed src, address indexed dst, uint256 amount, uint256 result, uint256 srcBalance, uint256 dstBalance, uint256 totalSupply, address referral ); uint256 public constant REFERRAL_SHARE = 20; // 1/share = 5% of LPs revenue uint256 public constant BASE_SUPPLY = 1000; // Total supply on first deposit uint256 public constant FEE_DENOMINATOR = 1e18; IFactory public factory; IERC20[] public tokens; mapping(IERC20 => bool) public isToken; mapping(IERC20 => SwapVolumes) public volumes; mapping(IERC20 => VirtualBalance.Data) public virtualBalancesForAddition; mapping(IERC20 => VirtualBalance.Data) public virtualBalancesForRemoval; constructor(IERC20[] memory assets, string memory name, string memory symbol) public ERC20(name, symbol) { require(bytes(name).length > 0, "Mooniswap: name is empty"); require(bytes(symbol).length > 0, "Mooniswap: symbol is empty"); require(assets.length == 2, "Mooniswap: only 2 tokens allowed"); factory = IFactory(msg.sender); tokens = assets; for (uint i = 0; i < assets.length; i++) { require(!isToken[assets[i]], "Mooniswap: duplicate tokens"); isToken[assets[i]] = true; } } function fee() public view returns(uint256) { return factory.fee(); } function getTokens() external view returns(IERC20[] memory) { return tokens; } function decayPeriod() external pure returns(uint256) { return VirtualBalance.DECAY_PERIOD; } function getBalanceForAddition(IERC20 token) public view returns(uint256) { uint256 balance = token.uniBalanceOf(address(this)); return Math.max(virtualBalancesForAddition[token].current(balance), balance); } function getBalanceForRemoval(IERC20 token) public view returns(uint256) { uint256 balance = token.uniBalanceOf(address(this)); return Math.min(virtualBalancesForRemoval[token].current(balance), balance); } function getReturn(IERC20 src, IERC20 dst, uint256 amount) external view returns(uint256) { return _getReturn(src, dst, amount, getBalanceForAddition(src), getBalanceForRemoval(dst)); } function deposit(uint256[] calldata amounts, uint256[] calldata minAmounts) external payable nonReentrant returns(uint256 fairSupply) { IERC20[] memory _tokens = tokens; require(amounts.length == _tokens.length, "Mooniswap: wrong amounts length"); require(msg.value == (_tokens[0].isETH() ? amounts[0] : (_tokens[1].isETH() ? amounts[1] : 0)), "Mooniswap: wrong value usage"); uint256[] memory realBalances = new uint256[](amounts.length); for (uint i = 0; i < realBalances.length; i++) { realBalances[i] = _tokens[i].uniBalanceOf(address(this)).sub(_tokens[i].isETH() ? msg.value : 0); } uint256 totalSupply = totalSupply(); if (totalSupply == 0) { fairSupply = BASE_SUPPLY.mul(99); _mint(address(this), BASE_SUPPLY); // Donate up to 1% // Use the greatest token amount but not less than 99k for the initial supply for (uint i = 0; i < amounts.length; i++) { fairSupply = Math.max(fairSupply, amounts[i]); } } else { // Pre-compute fair supply fairSupply = type(uint256).max; for (uint i = 0; i < amounts.length; i++) { fairSupply = Math.min(fairSupply, totalSupply.mul(amounts[i]).div(realBalances[i])); } } uint256 fairSupplyCached = fairSupply; for (uint i = 0; i < amounts.length; i++) { require(amounts[i] > 0, "Mooniswap: amount is zero"); uint256 amount = (totalSupply == 0) ? amounts[i] : realBalances[i].mul(fairSupplyCached).add(totalSupply - 1).div(totalSupply); require(amount >= minAmounts[i], "Mooniswap: minAmount not reached"); _tokens[i].uniTransferFromSenderToThis(amount); if (totalSupply > 0) { uint256 confirmed = _tokens[i].uniBalanceOf(address(this)).sub(realBalances[i]); fairSupply = Math.min(fairSupply, totalSupply.mul(confirmed).div(realBalances[i])); } } if (totalSupply > 0) { for (uint i = 0; i < amounts.length; i++) { virtualBalancesForRemoval[_tokens[i]].scale(realBalances[i], totalSupply.add(fairSupply), totalSupply); virtualBalancesForAddition[_tokens[i]].scale(realBalances[i], totalSupply.add(fairSupply), totalSupply); } } require(fairSupply > 0, "Mooniswap: result is not enough"); _mint(msg.sender, fairSupply); emit Deposited(msg.sender, fairSupply); } function withdraw(uint256 amount, uint256[] memory minReturns) external nonReentrant { uint256 totalSupply = totalSupply(); _burn(msg.sender, amount); for (uint i = 0; i < tokens.length; i++) { IERC20 token = tokens[i]; uint256 preBalance = token.uniBalanceOf(address(this)); uint256 value = preBalance.mul(amount).div(totalSupply); token.uniTransfer(msg.sender, value); require(i >= minReturns.length || value >= minReturns[i], "Mooniswap: result is not enough"); virtualBalancesForAddition[token].scale(preBalance, totalSupply.sub(amount), totalSupply); virtualBalancesForRemoval[token].scale(preBalance, totalSupply.sub(amount), totalSupply); } emit Withdrawn(msg.sender, amount); } function swap(IERC20 src, IERC20 dst, uint256 amount, uint256 minReturn, address referral) external payable nonReentrant returns(uint256 result) { require(msg.value == (src.isETH() ? amount : 0), "Mooniswap: wrong value usage"); Balances memory balances = Balances({ src: src.uniBalanceOf(address(this)).sub(src.isETH() ? msg.value : 0), dst: dst.uniBalanceOf(address(this)) }); // catch possible airdrops and external balance changes for deflationary tokens uint256 srcAdditionBalance = Math.max(virtualBalancesForAddition[src].current(balances.src), balances.src); uint256 dstRemovalBalance = Math.min(virtualBalancesForRemoval[dst].current(balances.dst), balances.dst); src.uniTransferFromSenderToThis(amount); uint256 confirmed = src.uniBalanceOf(address(this)).sub(balances.src); result = _getReturn(src, dst, confirmed, srcAdditionBalance, dstRemovalBalance); require(result > 0 && result >= minReturn, "Mooniswap: return is not enough"); dst.uniTransfer(msg.sender, result); // Update virtual balances to the same direction only at imbalanced state if (srcAdditionBalance != balances.src) { virtualBalancesForAddition[src].set(srcAdditionBalance.add(confirmed)); } if (dstRemovalBalance != balances.dst) { virtualBalancesForRemoval[dst].set(dstRemovalBalance.sub(result)); } // Update virtual balances to the opposite direction virtualBalancesForRemoval[src].update(balances.src); virtualBalancesForAddition[dst].update(balances.dst); if (referral != address(0)) { uint256 invariantRatio = uint256(1e36); invariantRatio = invariantRatio.mul(balances.src.add(confirmed)).div(balances.src); invariantRatio = invariantRatio.mul(balances.dst.sub(result)).div(balances.dst); if (invariantRatio > 1e36) { // calculate share only if invariant increased uint256 referralShare = invariantRatio.sqrt().sub(1e18).mul(totalSupply()).div(1e18).div(REFERRAL_SHARE); if (referralShare > 0) { _mint(referral, referralShare); } } } emit Swapped(msg.sender, address(src), address(dst), confirmed, result, balances.src, balances.dst, totalSupply(), referral); // Overflow of uint128 is desired volumes[src].confirmed += uint128(confirmed); volumes[src].result += uint128(result); } function rescueFunds(IERC20 token, uint256 amount) external nonReentrant onlyOwner { uint256[] memory balances = new uint256[](tokens.length); for (uint i = 0; i < balances.length; i++) { balances[i] = tokens[i].uniBalanceOf(address(this)); } token.uniTransfer(msg.sender, amount); for (uint i = 0; i < balances.length; i++) { require(tokens[i].uniBalanceOf(address(this)) >= balances[i], "Mooniswap: access denied"); } require(balanceOf(address(this)) >= BASE_SUPPLY, "Mooniswap: access denied"); } function _getReturn(IERC20 src, IERC20 dst, uint256 amount, uint256 srcBalance, uint256 dstBalance) internal view returns(uint256) { if (isToken[src] && isToken[dst] && src != dst && amount > 0) { uint256 taxedAmount = amount.sub(amount.mul(fee()).div(FEE_DENOMINATOR)); return taxedAmount.mul(dstBalance).div(srcBalance.add(taxedAmount)); } } } // File: contracts/MooniFactory.sol pragma solidity ^0.6.0; contract MooniFactory is Ownable { using UniERC20 for IERC20; event Deployed( address indexed mooniswap, address indexed token1, address indexed token2 ); uint256 public constant MAX_FEE = 0.003e18; // 0.3% uint256 public fee; Mooniswap[] public allPools; mapping(Mooniswap => bool) public isPool; mapping(IERC20 => mapping(IERC20 => Mooniswap)) public pools; function getAllPools() external view returns(Mooniswap[] memory) { return allPools; } function setFee(uint256 newFee) external onlyOwner { require(newFee <= MAX_FEE, "Factory: fee should be <= 0.3%"); fee = newFee; } function deploy(IERC20 tokenA, IERC20 tokenB) public returns(Mooniswap pool) { require(tokenA != tokenB, "Factory: not support same tokens"); require(pools[tokenA][tokenB] == Mooniswap(0), "Factory: pool already exists"); (IERC20 token1, IERC20 token2) = sortTokens(tokenA, tokenB); IERC20[] memory tokens = new IERC20[](2); tokens[0] = token1; tokens[1] = token2; string memory symbol1 = token1.uniSymbol(); string memory symbol2 = token2.uniSymbol(); pool = new Mooniswap( tokens, string(abi.encodePacked("Mooniswap V1 (", symbol1, "-", symbol2, ")")), string(abi.encodePacked("MOON-V1-", symbol1, "-", symbol2)) ); pool.transferOwnership(owner()); pools[token1][token2] = pool; pools[token2][token1] = pool; allPools.push(pool); isPool[pool] = true; emit Deployed( address(pool), address(token1), address(token2) ); } function sortTokens(IERC20 tokenA, IERC20 tokenB) public pure returns(IERC20, IERC20) { if (tokenA < tokenB) { return (tokenA, tokenB); } return (tokenB, tokenA); } }
File 2 of 3: Mooniswap
/* MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXK0OxdoollccccclodkOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0kdlc;'.. .,:loxkk0KXNWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKkoc,.. .':ox0XNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOd:'. .;lxKNWMMMMMMMMMMMMMMMWWNNNNNNNNWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo:. .,lkXWMMMMMMMMMWXKOxddol:;;,''.....'',,;:cldxO0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXxc' .;d0NMMMMMMMWXOxl:,.. ..,:ldOKNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXx:. .;dKWMMMMMWN0dc,. .,cdOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNkc. 'l0NMMMMMN0d:'. .:d0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMW0o' .;xXMMMMMNOo,. .....''',,'''.... .'lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMNOc. .:kNMMMMW0o, ..,:loxk0KKXXNNNWWWNNNNXKK0kxol:,.. .cONMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMNk;. .;ONMMMMXx;. .,cdkKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOdc;. ,oKWMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMNk; ,kNMMMW0l. ':dOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOd:' .cOWMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMWO: .dXMMMW0c. .;oONWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .:ONMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMWKc. :0WMMWKl. .;dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNWMMMMMMMMMMWKx:. .:OWMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMNx. .dNMMMXd. ,o0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0kxOXWMMMMMMMMWKd;. .cKWMMMMMMMMMMMMMMM MMMMMMMMMMMMMMW0: ,OWMMWO, .:kNMMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMMMMMMMMMMMMMMMMMMWXxc,:d0NMMMMMMMMNOc. .xNMMMMMMMMMMMMMM MMMMMMMMMMMMMNx. :KMMMXo..c0WMMMMMMMMMMMMMMMMMMMMXxl:;,;;:codkKNMMMMMMMMMMMMMMMMMMMMMMNk;..,o0WMMMMMMMWKo. :KMMMMMMMMMMMMM MMMMMMMMMMMMXl. cXMMW0:.c0WMMMMMMMMMMMMWWNNXXXNNWXd'..;;'.. .,lkNMMW00NMMMMMMMMMMMMMMMNk; .;dKWMMMMMMWKo. 'kWMMMMMMMMMMM MMMMMMMMMMMK: cXMMWk;;OWMMMMMMMMMN0xoc;,'.....';cll'.oKNX0xol, ,xXNc.,xXMMMMMMMMMMMMMMMNx' .l0WMMMMMMWKl. .dNMMMMMMMMMM MMMMMMMMMM0; cXMMWk:dXMMMMMMMMW0o,. ..,:clllllcc:;,..;0WMMMMNO:. ;Ol. ;0MMMMMMMMMMMMMMMMXl. .:OWMMMMMMWO; .lNMMMMMMMMM MMMMMMMMM0, ;KMMWklkNWMMMMMMMKl. .';coxOXWMMMMWNKOdxKWMMMMMWk, .:l: ,0MMMMMMMMMMMMMMMMWO, .c0WMMMMMMXo. lXMMMMMMMM MMMMMMMM0, '0MMNx,''lXMMMMMWk' .,cdxkkkxdxxOKXWMMMMMMWNXNMMMMMM0, .kK; cNMMMMMMN0XMMMMMMMMKc .oXMMMMMMWO, lNMMMMMMM MMMMMMM0; .xWMKc. . .kWMMMNd. .l0NMMMMMMMMMMWNXNWMMMMMMMWNNWMMMMMk. 'OWd. .OMMMMXx:oXMMMMMMMMMNo. ,kWMMMMMMK: .dWMMMMMM MMMMMMX: cXM0; .l0o..:ool, .lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMX; ;XMO. .dWWKo'.:KMMMMMMMMMMMWx. .oXMMMMMMXc .kWMMMMM MMMMMNl .OMX: .oNMWOc'...':dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNc.dWMO. lOl. ,0MMMMMMMMMMMMMWx. :KMMMMMMXl ;KMMMMM MMMMWx. lNMx. ;XMMMMMNXKXNWMWNWMMMMMMMMMMMMMMMXO0WMMMMMMMMMMMMMMMK::XMWx. ...'.'OMMMMMMMMMMMMMMMWd. ;0MMMMMMXc oWMMMM MMMMK, .kMNl cNMMMMMMMWNX0kxONMMMMMMMMMMMMMMWd..,cok0NWMMMMMMMMM0xKMMX; .cd;'kWMMMMMMMMMMMMMMMMNo ,0MMMMMMK: '0MMMM MMMWo .cl:. .,ooolllllc::ld0WMMMMMMMMMMMMMMMNl .':oOXNMMMMMWMMWO: ;d00:.xWMMMMMMMMMMMMMMMMMMX: ;KMMMMMM0' oWMMM MMM0' .':ok0KKK0OkxxkOKNWMMMMMMMMMMMMMMMMMMWo ..;OWMMMMWO:. ,OWK:.dWMMMMMMMMMMMMMMMMMMMMO' :XMMMMMWd. ,KMMM MMWo .l0NWMMMMMMMMMMMMMMMMMMMMMMMMWXKWMMMMW0o' .kWMWO:. .cOOOO:.oNMMMMMMMMMNXWMMMMMMMMMWo .oWMMMMMX: .kMMM MMK, .OMMMMMMMMMMMMMMMMMMMMMMMMN0d:.cXMMMKc. .ok:. ..;KMMX:.lNMMMMMMMMMWxlKMMMMMMMMMM0, 'OMMMMMWk. oWMM MMx. 'OXXNMMMMMMMMMMMMMMMMMWXkl,. lWMWO' ,O0dd0Kc .kMMMMMMMMMWk' cXMMMMMMMMMWl lNMMMMMX; cNMM MNl .dOKNMMMMMMMMMMMMMMWKxc. lWM0, 'xXWN0: ;0MMMWN0xl,. 'cdOXWMMMMMk. 'OMMMMMWd. ;XMM MX; ;XMMMMMMMMNOkXMMWKx;. ,KWo .:c, ;KMMWN0ko;. 'cdOXWMMMMMK, dWMMMMMO. ,KMM M0' ,KMMMMXKN0:.oWW0c. ;d; lNMMMMMMWO'.dNMMMMMMMMMMNc :XMMMMMK, ;KMM MO. '0MMM0lkO, 'ONd. .oNMMMMMMWkdNMMMMMMMMMMMWo ,KMMMMMX: ;XMM Mk. .OMM0,,x; ;Ol ..',. ;KMMMMMMMNNMMMMMMMMMMMMWo '0MMMMMNc cNMM Mx. .dW0, ,:. ,c. .:0Xk:. lNMMMMMMMMMMMMMMMMMMMMMWo .OMMMMMNc oWMM Mk. c0: .. . .,xOd0NO; '0MMMMMMMMMMMMMWWMMMMMMMWo .OMMMMMN: .kMMM Mk. .:. .,. .cx: .lKXl lWMMMMMMMMMMMWNxlONMMMMMNc '0MMMMMX; ;XMMM M0' .:c. .. .,:;,,l0Xl .xMMMMMMMMMMMWNk,.:ONMMMMX; ;XMMMMM0' .dWMMM MK; 'dl. .....''',:k0d;. oWMMMMMMMMMMMMWOo0MMMMMMO. oWMMMMMx. ,KMMMM MNc :kl. ...... ,c;. :XMMMMMMMMMMMMMWWWMMMMMWo .kMMMMMNc .dWMMMM MWd. c0l. .OMMMMMMMMMMMMMMMMMMMMMK; :XMMMMMO' :XMMMMM MM0' :0d. . lNMMMMMMMMMMMMMMMMMMMWd. .kMMMMMNl '0MMMMMM MMNl '0k. .. 'c. .OMMMMMMMMMMMMMMMMMMM0, lNMMMMMO. .kWMMMMMM MMMO. .dK; ;0O; :d' ;KMMMMMMMMMMMMMMMMMNl ,KMMMMMX: .xWMMMWXNM MMMNc ,0d. .OMMNk:. .x0xo, cXMMMMMMMMMMMMMMMWd. 'OMMMMMNo .dWMMMWOkNM MMMMO' c0; .dWMMMMW0l. ;dooxl. :0WMMMMMMMMMMMMWk. .kWMMMMWx. .xWMMMWxc0MM MMMMWd. ok. :XMMMMMMMWO, .:dc 'OWMMMMMMMMMMWO' .kWMMMMWk. 'kWMMMNo,dWMM MMMMMX: cd. .kWMMMMMMMMWk. .. .,cc. :XMMMMMMMMMWk' 'OWMMMMWk. :0MMMMKc.cXMMM MMMMMM0, .'. :XMMMMMMMMMMNc 'c;ll. .. .OMMMMMMMMWx. :KMMMMMNx. .oNMMMWO, ;KMMMM MMMMMMWO' .xWMMMMMMMMMMMk:. ,0KOOc .OMMMMMMMNo. .oXMMMMMXo. ;OWMMMXl. 'OMMMMM MMMMMMMWk. ,0MMMMMMMMMMMMX0: .:d00l. lNMMMMMW0: ;OWMMMMW0: 'xNMMMNk, 'OWMMMMM MMMMMMMMWx. :XMMMMMNNMMMMMMWk. .',. 'xNMMMMMNx. ,xNMMMMMNx. .oXMMMWO:. 'OWMMMMMM MMMMMMMMMWk. cNMMMMNdxNMMMMMMWO:. .;xXMMMMMWO: 'dXMMMMMWO; .oKWMMW0c. 'OWMMMMMMM MMMMMMMMMMWO, cNWNKk:..:kKNWMMMMWKxc'. .,oONMMMMMW0c. .;xXMMMMMWKl..,dXWMMNOc. ;0WMMMMMMMM MMMMMMMMMMMMK: cNWN0o' 'oONWMMMMMMMWN0dc;''';lxKNMMMMMMW0l. .cONMMMMMWKl'.ckNMMMNk;. cKMMMMMMMMMM MMMMMMMMMMMMMXo. cNMMMMKccKMMMMMMMMMMMMMMMMWNNNWMMMMMMMMNOc. .:xXWMMMMMWOl;:dKWMMW0o' .dNMMMMMMMMMMM MMMMMMMMMMMMMMWk' lNMMMMMXXMMMMMMMMMMMMMMMMMMMMMMMMMMMWKx;. .,lkXWMMMMMWXOdoxKWMMWKd;. ;OWMMMMMMMMMMMM MMMMMMMMMMMMMMMMKl. oWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXkc,';lxKNMMMMMMMWX0OOXWMMN0d;. .oXMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMWk; lXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOxdxOXWMMMMMMMMMMMWNWMMWKxl,. .:0WMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMXd' .:ok0NWMMMMMMMMMMMMMMMMMMMMMMMWNWWMMMMMMMMMMMMMMMMWX0xl,. ,kNMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMXo. .':ldOKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXKOdc;.. 'xNMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMWKo' .';ccldxO0KXXNWWWWWWWWWNNXKKOkxol:,.. ,xXMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMWXd, ....',,,,,,,,,'.... .;kNMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMNk:. .l0WMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKo,. .:xXWMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo, .;dKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo;. .:xKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKxc'. .;oOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0xl;. .':oOXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXOdl;'. ..,cokKNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNKOxoc;,... ..';:ldk0XWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWXK0Okxdollcccc:::cccclloddkO0KXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM ███╗ ███╗ ██████╗ ██████╗ ███╗ ██╗██╗███████╗██╗ ██╗ █████╗ ██████╗ ███████╗██╗ ██╗ ██████╗██╗ ██╗ █████╗ ███╗ ██╗ ██████╗ ███████╗ ████╗ ████║██╔═══██╗██╔═══██╗████╗ ██║██║██╔════╝██║ ██║██╔══██╗██╔══██╗██╔════╝╚██╗██╔╝██╔════╝██║ ██║██╔══██╗████╗ ██║██╔════╝ ██╔════╝ ██╔████╔██║██║ ██║██║ ██║██╔██╗ ██║██║███████╗██║ █╗ ██║███████║██████╔╝█████╗ ╚███╔╝ ██║ ███████║███████║██╔██╗ ██║██║ ███╗█████╗ ██║╚██╔╝██║██║ ██║██║ ██║██║╚██╗██║██║╚════██║██║███╗██║██╔══██║██╔═══╝ ██╔══╝ ██╔██╗ ██║ ██╔══██║██╔══██║██║╚██╗██║██║ ██║██╔══╝ ██║ ╚═╝ ██║╚██████╔╝╚██████╔╝██║ ╚████║██║███████║╚███╔███╔╝██║ ██║██║██╗ ███████╗██╔╝ ██╗╚██████╗██║ ██║██║ ██║██║ ╚████║╚██████╔╝███████╗ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚══════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚══════╝ ██████╗ ██╗ ██╗ ██╗██╗███╗ ██╗ ██████╗██╗ ██╗ ██╔══██╗╚██╗ ██╔╝ ███║██║████╗ ██║██╔════╝██║ ██║ ██████╔╝ ╚████╔╝ ╚██║██║██╔██╗ ██║██║ ███████║ ██╔══██╗ ╚██╔╝ ██║██║██║╚██╗██║██║ ██╔══██║ ██████╔╝ ██║ ██║██║██║ ╚████║╚██████╗██║ ██║ ╚═════╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═══╝ ╚═════╝╚═╝ ╚═╝ */ // File: @openzeppelin/contracts/GSN/Context.sol // SPDX-License-Identifier: MIT pragma solidity ^0.6.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 GSN 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 payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } } // File: @openzeppelin/contracts/access/Ownable.sol pragma solidity ^0.6.0; /** * @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. */ 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 () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = 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"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // File: @openzeppelin/contracts/utils/ReentrancyGuard.sol pragma solidity ^0.6.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor () internal { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } } // File: @openzeppelin/contracts/math/Math.sol pragma solidity ^0.6.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @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, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } } // File: @openzeppelin/contracts/math/SafeMath.sol pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: @openzeppelin/contracts/utils/Address.sol pragma solidity ^0.6.2; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/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"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain`call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * 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 functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File: @openzeppelin/contracts/token/ERC20/ERC20.sol pragma solidity ^0.6.0; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; using Address for address; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens. * * This is internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ 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); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.6.0; /** * @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 SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @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' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. 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"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/libraries/UniERC20.sol pragma solidity ^0.6.0; library UniERC20 { using SafeMath for uint256; using SafeERC20 for IERC20; function isETH(IERC20 token) internal pure returns(bool) { return (address(token) == address(0)); } function uniBalanceOf(IERC20 token, address account) internal view returns (uint256) { if (isETH(token)) { return account.balance; } else { return token.balanceOf(account); } } function uniTransfer(IERC20 token, address payable to, uint256 amount) internal { if (amount > 0) { if (isETH(token)) { to.transfer(amount); } else { token.safeTransfer(to, amount); } } } function uniTransferFromSenderToThis(IERC20 token, uint256 amount) internal { if (amount > 0) { if (isETH(token)) { require(msg.value >= amount, "UniERC20: not enough value"); if (msg.value > amount) { // Return remainder if exist msg.sender.transfer(msg.value.sub(amount)); } } else { token.safeTransferFrom(msg.sender, address(this), amount); } } } function uniSymbol(IERC20 token) internal view returns(string memory) { if (isETH(token)) { return "ETH"; } (bool success, bytes memory data) = address(token).staticcall{ gas: 20000 }( abi.encodeWithSignature("symbol()") ); if (!success) { (success, data) = address(token).staticcall{ gas: 20000 }( abi.encodeWithSignature("SYMBOL()") ); } if (success && data.length >= 96) { (uint256 offset, uint256 len) = abi.decode(data, (uint256, uint256)); if (offset == 0x20 && len > 0 && len <= 256) { return string(abi.decode(data, (bytes))); } } if (success && data.length == 32) { uint len = 0; while (len < data.length && data[len] >= 0x20 && data[len] <= 0x7E) { len++; } if (len > 0) { bytes memory result = new bytes(len); for (uint i = 0; i < len; i++) { result[i] = data[i]; } return string(result); } } return _toHex(address(token)); } function _toHex(address account) private pure returns(string memory) { return _toHex(abi.encodePacked(account)); } function _toHex(bytes memory data) private pure returns(string memory) { bytes memory str = new bytes(2 + data.length * 2); str[0] = "0"; str[1] = "x"; uint j = 2; for (uint i = 0; i < data.length; i++) { uint a = uint8(data[i]) >> 4; uint b = uint8(data[i]) & 0x0f; str[j++] = byte(uint8(a + 48 + (a/10)*39)); str[j++] = byte(uint8(b + 48 + (b/10)*39)); } return string(str); } } // File: contracts/libraries/Sqrt.sol pragma solidity ^0.6.0; library Sqrt { // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint256 y) internal pure returns (uint256) { if (y > 3) { uint256 z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } return z; } else if (y != 0) { return 1; } else { return 0; } } } // File: contracts/Mooniswap.sol pragma solidity ^0.6.0; interface IFactory { function fee() external view returns(uint256); } library VirtualBalance { using SafeMath for uint256; struct Data { uint216 balance; uint40 time; } uint256 public constant DECAY_PERIOD = 5 minutes; function set(VirtualBalance.Data storage self, uint256 balance) internal { self.balance = uint216(balance); self.time = uint40(block.timestamp); } function update(VirtualBalance.Data storage self, uint256 realBalance) internal { set(self, current(self, realBalance)); } function scale(VirtualBalance.Data storage self, uint256 realBalance, uint256 num, uint256 denom) internal { set(self, current(self, realBalance).mul(num).add(denom.sub(1)).div(denom)); } function current(VirtualBalance.Data memory self, uint256 realBalance) internal view returns(uint256) { uint256 timePassed = Math.min(DECAY_PERIOD, block.timestamp.sub(self.time)); uint256 timeRemain = DECAY_PERIOD.sub(timePassed); return uint256(self.balance).mul(timeRemain).add( realBalance.mul(timePassed) ).div(DECAY_PERIOD); } } contract Mooniswap is ERC20, ReentrancyGuard, Ownable { using Sqrt for uint256; using SafeMath for uint256; using UniERC20 for IERC20; using VirtualBalance for VirtualBalance.Data; struct Balances { uint256 src; uint256 dst; } struct SwapVolumes { uint128 confirmed; uint128 result; } event Deposited( address indexed account, uint256 amount ); event Withdrawn( address indexed account, uint256 amount ); event Swapped( address indexed account, address indexed src, address indexed dst, uint256 amount, uint256 result, uint256 srcBalance, uint256 dstBalance, uint256 totalSupply, address referral ); uint256 public constant REFERRAL_SHARE = 20; // 1/share = 5% of LPs revenue uint256 public constant BASE_SUPPLY = 1000; // Total supply on first deposit uint256 public constant FEE_DENOMINATOR = 1e18; IFactory public factory; IERC20[] public tokens; mapping(IERC20 => bool) public isToken; mapping(IERC20 => SwapVolumes) public volumes; mapping(IERC20 => VirtualBalance.Data) public virtualBalancesForAddition; mapping(IERC20 => VirtualBalance.Data) public virtualBalancesForRemoval; constructor(IERC20[] memory assets, string memory name, string memory symbol) public ERC20(name, symbol) { require(bytes(name).length > 0, "Mooniswap: name is empty"); require(bytes(symbol).length > 0, "Mooniswap: symbol is empty"); require(assets.length == 2, "Mooniswap: only 2 tokens allowed"); factory = IFactory(msg.sender); tokens = assets; for (uint i = 0; i < assets.length; i++) { require(!isToken[assets[i]], "Mooniswap: duplicate tokens"); isToken[assets[i]] = true; } } function fee() public view returns(uint256) { return factory.fee(); } function getTokens() external view returns(IERC20[] memory) { return tokens; } function decayPeriod() external pure returns(uint256) { return VirtualBalance.DECAY_PERIOD; } function getBalanceForAddition(IERC20 token) public view returns(uint256) { uint256 balance = token.uniBalanceOf(address(this)); return Math.max(virtualBalancesForAddition[token].current(balance), balance); } function getBalanceForRemoval(IERC20 token) public view returns(uint256) { uint256 balance = token.uniBalanceOf(address(this)); return Math.min(virtualBalancesForRemoval[token].current(balance), balance); } function getReturn(IERC20 src, IERC20 dst, uint256 amount) external view returns(uint256) { return _getReturn(src, dst, amount, getBalanceForAddition(src), getBalanceForRemoval(dst)); } function deposit(uint256[] calldata amounts, uint256[] calldata minAmounts) external payable nonReentrant returns(uint256 fairSupply) { IERC20[] memory _tokens = tokens; require(amounts.length == _tokens.length, "Mooniswap: wrong amounts length"); require(msg.value == (_tokens[0].isETH() ? amounts[0] : (_tokens[1].isETH() ? amounts[1] : 0)), "Mooniswap: wrong value usage"); uint256[] memory realBalances = new uint256[](amounts.length); for (uint i = 0; i < realBalances.length; i++) { realBalances[i] = _tokens[i].uniBalanceOf(address(this)).sub(_tokens[i].isETH() ? msg.value : 0); } uint256 totalSupply = totalSupply(); if (totalSupply == 0) { fairSupply = BASE_SUPPLY.mul(99); _mint(address(this), BASE_SUPPLY); // Donate up to 1% // Use the greatest token amount but not less than 99k for the initial supply for (uint i = 0; i < amounts.length; i++) { fairSupply = Math.max(fairSupply, amounts[i]); } } else { // Pre-compute fair supply fairSupply = type(uint256).max; for (uint i = 0; i < amounts.length; i++) { fairSupply = Math.min(fairSupply, totalSupply.mul(amounts[i]).div(realBalances[i])); } } uint256 fairSupplyCached = fairSupply; for (uint i = 0; i < amounts.length; i++) { require(amounts[i] > 0, "Mooniswap: amount is zero"); uint256 amount = (totalSupply == 0) ? amounts[i] : realBalances[i].mul(fairSupplyCached).add(totalSupply - 1).div(totalSupply); require(amount >= minAmounts[i], "Mooniswap: minAmount not reached"); _tokens[i].uniTransferFromSenderToThis(amount); if (totalSupply > 0) { uint256 confirmed = _tokens[i].uniBalanceOf(address(this)).sub(realBalances[i]); fairSupply = Math.min(fairSupply, totalSupply.mul(confirmed).div(realBalances[i])); } } if (totalSupply > 0) { for (uint i = 0; i < amounts.length; i++) { virtualBalancesForRemoval[_tokens[i]].scale(realBalances[i], totalSupply.add(fairSupply), totalSupply); virtualBalancesForAddition[_tokens[i]].scale(realBalances[i], totalSupply.add(fairSupply), totalSupply); } } require(fairSupply > 0, "Mooniswap: result is not enough"); _mint(msg.sender, fairSupply); emit Deposited(msg.sender, fairSupply); } function withdraw(uint256 amount, uint256[] memory minReturns) external nonReentrant { uint256 totalSupply = totalSupply(); _burn(msg.sender, amount); for (uint i = 0; i < tokens.length; i++) { IERC20 token = tokens[i]; uint256 preBalance = token.uniBalanceOf(address(this)); uint256 value = preBalance.mul(amount).div(totalSupply); token.uniTransfer(msg.sender, value); require(i >= minReturns.length || value >= minReturns[i], "Mooniswap: result is not enough"); virtualBalancesForAddition[token].scale(preBalance, totalSupply.sub(amount), totalSupply); virtualBalancesForRemoval[token].scale(preBalance, totalSupply.sub(amount), totalSupply); } emit Withdrawn(msg.sender, amount); } function swap(IERC20 src, IERC20 dst, uint256 amount, uint256 minReturn, address referral) external payable nonReentrant returns(uint256 result) { require(msg.value == (src.isETH() ? amount : 0), "Mooniswap: wrong value usage"); Balances memory balances = Balances({ src: src.uniBalanceOf(address(this)).sub(src.isETH() ? msg.value : 0), dst: dst.uniBalanceOf(address(this)) }); // catch possible airdrops and external balance changes for deflationary tokens uint256 srcAdditionBalance = Math.max(virtualBalancesForAddition[src].current(balances.src), balances.src); uint256 dstRemovalBalance = Math.min(virtualBalancesForRemoval[dst].current(balances.dst), balances.dst); src.uniTransferFromSenderToThis(amount); uint256 confirmed = src.uniBalanceOf(address(this)).sub(balances.src); result = _getReturn(src, dst, confirmed, srcAdditionBalance, dstRemovalBalance); require(result > 0 && result >= minReturn, "Mooniswap: return is not enough"); dst.uniTransfer(msg.sender, result); // Update virtual balances to the same direction only at imbalanced state if (srcAdditionBalance != balances.src) { virtualBalancesForAddition[src].set(srcAdditionBalance.add(confirmed)); } if (dstRemovalBalance != balances.dst) { virtualBalancesForRemoval[dst].set(dstRemovalBalance.sub(result)); } // Update virtual balances to the opposite direction virtualBalancesForRemoval[src].update(balances.src); virtualBalancesForAddition[dst].update(balances.dst); if (referral != address(0)) { uint256 invariantRatio = uint256(1e36); invariantRatio = invariantRatio.mul(balances.src.add(confirmed)).div(balances.src); invariantRatio = invariantRatio.mul(balances.dst.sub(result)).div(balances.dst); if (invariantRatio > 1e36) { // calculate share only if invariant increased uint256 referralShare = invariantRatio.sqrt().sub(1e18).mul(totalSupply()).div(1e18).div(REFERRAL_SHARE); if (referralShare > 0) { _mint(referral, referralShare); } } } emit Swapped(msg.sender, address(src), address(dst), confirmed, result, balances.src, balances.dst, totalSupply(), referral); // Overflow of uint128 is desired volumes[src].confirmed += uint128(confirmed); volumes[src].result += uint128(result); } function rescueFunds(IERC20 token, uint256 amount) external nonReentrant onlyOwner { uint256[] memory balances = new uint256[](tokens.length); for (uint i = 0; i < balances.length; i++) { balances[i] = tokens[i].uniBalanceOf(address(this)); } token.uniTransfer(msg.sender, amount); for (uint i = 0; i < balances.length; i++) { require(tokens[i].uniBalanceOf(address(this)) >= balances[i], "Mooniswap: access denied"); } require(balanceOf(address(this)) >= BASE_SUPPLY, "Mooniswap: access denied"); } function _getReturn(IERC20 src, IERC20 dst, uint256 amount, uint256 srcBalance, uint256 dstBalance) internal view returns(uint256) { if (isToken[src] && isToken[dst] && src != dst && amount > 0) { uint256 taxedAmount = amount.sub(amount.mul(fee()).div(FEE_DENOMINATOR)); return taxedAmount.mul(dstBalance).div(srcBalance.add(taxedAmount)); } } }
File 3 of 3: VotingToken
{"ICommonUtilities.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface ICommonUtilities {\r\n function toString(address _addr) external pure returns(string memory);\r\n function toString(uint _i) external pure returns(string memory);\r\n function toUint256(bytes calldata bs) external pure returns(uint256 x);\r\n function toAddress(bytes calldata b) external pure returns (address addr);\r\n function compareStrings(string calldata a, string calldata b) external pure returns(bool);\r\n function getFirstJSONPart(address sourceLocation, uint256 sourceLocationId, address location) external pure returns(bytes memory);\r\n function formatReturnAbiParametersArray(string calldata m) external pure returns(string memory);\r\n function toLowerCase(string calldata str) external pure returns(string memory);\r\n}"},"IERC20.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IERC20 {\r\n function totalSupply() external view returns (uint256);\r\n function balanceOf(address account) external view returns (uint256);\r\n function transfer(address recipient, uint256 amount) external returns (bool);\r\n function allowance(address owner, address spender) external view returns (uint256);\r\n function approve(address spender, uint256 amount) external returns (bool);\r\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\r\n\r\n event Transfer(address indexed from, address indexed to, uint256 value);\r\n event Approval(address indexed owner, address indexed spender, uint256 value);\r\n}"},"IERC721.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IERC721 {\n function ownerOf(uint256 _tokenId) external view returns (address);\n function transferFrom(address _from, address _to, uint256 _tokenId) external payable;\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;\n}"},"IERC721Receiver.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IERC721Receiver {\n function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);\n}"},"IMVDFunctionalitiesManager.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalitiesManager {\n\n function getProxy() external view returns (address);\n function setProxy() external;\n\n function init(address sourceLocation,\n uint256 getMinimumBlockNumberSourceLocationId, address getMinimumBlockNumberFunctionalityAddress,\n uint256 getEmergencyMinimumBlockNumberSourceLocationId, address getEmergencyMinimumBlockNumberFunctionalityAddress,\n uint256 getEmergencySurveyStakingSourceLocationId, address getEmergencySurveyStakingFunctionalityAddress,\n uint256 checkVoteResultSourceLocationId, address checkVoteResultFunctionalityAddress) external;\n\n function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender) external;\n function addFunctionality(string calldata codeName, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, uint256 position) external;\n function removeFunctionality(string calldata codeName) external returns(bool removed, uint256 position);\n function isValidFunctionality(address functionality) external view returns(bool);\n function isAuthorizedFunctionality(address functionality) external view returns(bool);\n function setCallingContext(address location) external returns(bool);\n function clearCallingContext() external;\n function getFunctionalityData(string calldata codeName) external view returns(address, uint256, string memory, address, uint256);\n function hasFunctionality(string calldata codeName) external view returns(bool);\n function getFunctionalitiesAmount() external view returns(uint256);\n function functionalitiesToJSON() external view returns(string memory);\n function functionalitiesToJSON(uint256 start, uint256 l) external view returns(string memory functionsJSONArray);\n function functionalityNames() external view returns(string memory);\n function functionalityNames(uint256 start, uint256 l) external view returns(string memory functionsJSONArray);\n function functionalityToJSON(string calldata codeName) external view returns(string memory);\n\n function preConditionCheck(string calldata codeName, bytes calldata data, uint8 submitable, address sender, uint256 value) external view returns(address location, bytes memory payload);\n\n function setupFunctionality(address proposalAddress) external returns (bool);\n}"},"IMVDFunctionalityModelsManager.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IMVDFunctionalityModelsManager {\r\n function init() external;\r\n function checkWellKnownFunctionalities(string calldata codeName, bool submitable, string calldata methodSignature, string calldata returnAbiParametersArray, bool isInternal, bool needsSender, string calldata replaces) external view;\r\n}"},"IMVDFunctionalityProposal.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalityProposal {\n\n function init(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces, address proxy) external;\n function setCollateralData(bool emergency, address sourceLocation, uint256 sourceLocationId, bool submitable, bool isInternal, bool needsSender, address proposer, uint256 votesHardCap) external;\n\n function getProxy() external view returns(address);\n function getCodeName() external view returns(string memory);\n function isEmergency() external view returns(bool);\n function getSourceLocation() external view returns(address);\n function getSourceLocationId() external view returns(uint256);\n function getLocation() external view returns(address);\n function isSubmitable() external view returns(bool);\n function getMethodSignature() external view returns(string memory);\n function getReturnAbiParametersArray() external view returns(string memory);\n function isInternal() external view returns(bool);\n function needsSender() external view returns(bool);\n function getReplaces() external view returns(string memory);\n function getProposer() external view returns(address);\n function getSurveyEndBlock() external view returns(uint256);\n function getSurveyDuration() external view returns(uint256);\n function isVotesHardCapReached() external view returns(bool);\n function getVotesHardCapToReach() external view returns(uint256);\n function toJSON() external view returns(string memory);\n function getVote(address addr) external view returns(uint256 accept, uint256 refuse);\n function getVotes() external view returns(uint256, uint256);\n function start() external;\n function disable() external;\n function isDisabled() external view returns(bool);\n function isTerminated() external view returns(bool);\n function accept(uint256 amount) external;\n function retireAccept(uint256 amount) external;\n function moveToAccept(uint256 amount) external;\n function refuse(uint256 amount) external;\n function retireRefuse(uint256 amount) external;\n function moveToRefuse(uint256 amount) external;\n function retireAll() external;\n function withdraw() external;\n function terminate() external;\n function set() external;\n\n event Accept(address indexed voter, uint256 amount);\n event RetireAccept(address indexed voter, uint256 amount);\n event MoveToAccept(address indexed voter, uint256 amount);\n event Refuse(address indexed voter, uint256 amount);\n event RetireRefuse(address indexed voter, uint256 amount);\n event MoveToRefuse(address indexed voter, uint256 amount);\n event RetireAll(address indexed voter, uint256 amount);\n}"},"IMVDFunctionalityProposalManager.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDFunctionalityProposalManager {\n function newProposal(string calldata codeName, address location, string calldata methodSignature, string calldata returnAbiParametersArray, string calldata replaces) external returns(address);\n function checkProposal(address proposalAddress) external;\n function getProxy() external view returns (address);\n function setProxy() external;\n function isValidProposal(address proposal) external view returns (bool);\n}"},"IMVDProxy.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDProxy {\n\n function init(address votingTokenAddress, address functionalityProposalManagerAddress, address stateHolderAddress, address functionalityModelsManagerAddress, address functionalitiesManagerAddress, address walletAddress) external;\n\n function getDelegates() external view returns(address,address,address,address,address,address);\n function getToken() external view returns(address);\n function getMVDFunctionalityProposalManagerAddress() external view returns(address);\n function getStateHolderAddress() external view returns(address);\n function getMVDFunctionalityModelsManagerAddress() external view returns(address);\n function getMVDFunctionalitiesManagerAddress() external view returns(address);\n function getMVDWalletAddress() external view returns(address);\n function setDelegate(uint256 position, address newAddress) external returns(address oldAddress);\n function changeProxy(address newAddress, bytes calldata initPayload) external;\n function isValidProposal(address proposal) external view returns (bool);\n function isAuthorizedFunctionality(address functionality) external view returns(bool);\n function newProposal(string calldata codeName, bool emergency, address sourceLocation, uint256 sourceLocationId, address location, bool submitable, string calldata methodSignature, string calldata returnParametersJSONArray, bool isInternal, bool needsSender, string calldata replaces) external returns(address proposalAddress);\n function startProposal(address proposalAddress) external;\n function disableProposal(address proposalAddress) external;\n function transfer(address receiver, uint256 value, address token) external;\n function transfer721(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external;\n function flushToWallet(address tokenAddress, bool is721, uint256 tokenId) external;\n function setProposal() external;\n function read(string calldata codeName, bytes calldata data) external view returns(bytes memory returnData);\n function submit(string calldata codeName, bytes calldata data) external payable returns(bytes memory returnData);\n function callFromManager(address location, bytes calldata payload) external returns(bool, bytes memory);\n function emitFromManager(string calldata codeName, address proposal, string calldata replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address location, bool submitable, string calldata methodSignature, bool isInternal, bool needsSender, address proposalAddress) external;\n\n function emitEvent(string calldata eventSignature, bytes calldata firstIndex, bytes calldata secondIndex, bytes calldata data) external;\n\n event ProxyChanged(address indexed newAddress);\n event DelegateChanged(uint256 position, address indexed oldAddress, address indexed newAddress);\n\n event Proposal(address proposal);\n event ProposalCheck(address indexed proposal);\n event ProposalSet(address indexed proposal, bool success);\n event FunctionalitySet(string codeName, address indexed proposal, string replaced, address replacedSourceLocation, uint256 replacedSourceLocationId, address indexed replacedLocation, bool replacedWasSubmitable, string replacedMethodSignature, bool replacedWasInternal, bool replacedNeededSender, address indexed replacedProposal);\n\n event Event(string indexed key, bytes32 indexed firstIndex, bytes32 indexed secondIndex, bytes data);\n}"},"IMVDWallet.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IMVDWallet {\n\n function getProxy() external view returns (address);\n\n function setProxy() external;\n\n function setNewWallet(address payable newWallet, address tokenAddress) external;\n\n function transfer(address receiver, uint256 value, address tokenAddress) external;\n \n function transfer(address receiver, uint256 tokenId, bytes calldata data, bool safe, address token) external;\n\n function flushToNewWallet(address token) external;\n\n function flush721ToNewWallet(uint256 tokenId, bytes calldata data, bool safe, address tokenAddress) external;\n}"},"IStateHolder.sol":{"content":"pragma solidity ^0.6.0;\n\ninterface IStateHolder {\n\n function init() external;\n\n function getProxy() external view returns (address);\n function setProxy() external;\n function toJSON() external view returns(string memory);\n function toJSON(uint256 start, uint256 l) external view returns(string memory);\n function getStateSize() external view returns (uint256);\n function exists(string calldata varName) external view returns(bool);\n function getDataType(string calldata varName) external view returns(string memory dataType);\n function clear(string calldata varName) external returns(string memory oldDataType, bytes memory oldVal);\n function setBytes(string calldata varName, bytes calldata val) external returns(bytes memory);\n function getBytes(string calldata varName) external view returns(bytes memory);\n function setString(string calldata varName, string calldata val) external returns(string memory);\n function getString(string calldata varName) external view returns (string memory);\n function setBool(string calldata varName, bool val) external returns(bool);\n function getBool(string calldata varName) external view returns (bool);\n function getUint256(string calldata varName) external view returns (uint256);\n function setUint256(string calldata varName, uint256 val) external returns(uint256);\n function getAddress(string calldata varName) external view returns (address);\n function setAddress(string calldata varName, address val) external returns (address);\n}"},"IVotingToken.sol":{"content":"pragma solidity ^0.6.0;\r\n\r\ninterface IVotingToken {\r\n function init(string calldata name, string calldata symbol, uint256 decimals, uint256 totalSupply) external;\r\n\r\n function getProxy() external view returns (address);\r\n function setProxy() external;\r\n\r\n function name() external view returns(string memory);\r\n function symbol() external view returns(string memory);\r\n function decimals() external view returns(uint256);\r\n\r\n function mint(uint256 amount) external;\r\n function burn(uint256 amount) external;\r\n\r\n function increaseAllowance(address spender, uint256 addedValue) external returns (bool);\r\n function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);\r\n}"},"VotingToken.sol":{"content":"pragma solidity ^0.6.0;\n\nimport \"./IMVDProxy.sol\";\nimport \"./IERC20.sol\";\nimport \"./IVotingToken.sol\";\nimport \"./IMVDFunctionalityProposalManager.sol\";\nimport \"./IMVDFunctionalitiesManager.sol\";\n\ncontract VotingToken is IERC20, IVotingToken {\n\n mapping (address =\u003e uint256) private _balances;\n\n mapping (address =\u003e mapping (address =\u003e uint256)) private _allowances;\n\n uint256 private _totalSupply;\n uint256 private _decimals;\n address private _proxy;\n string private _name;\n string private _symbol;\n\n constructor(string memory name, string memory symbol, uint256 decimals, uint256 totalSupply) public {\n if(totalSupply == 0) {\n return;\n }\n init(name, symbol, decimals, totalSupply);\n }\n\n function init(string memory name, string memory symbol, uint256 decimals, uint256 totalSupply) public override {\n require(_totalSupply == 0, \"Init already called!\");\n\n _name = name;\n _symbol = symbol;\n _decimals = decimals;\n _totalSupply = totalSupply * (10 ** decimals);\n _balances[msg.sender] = _totalSupply;\n emit Transfer(address(this), msg.sender, _totalSupply);\n }\n\n receive() external payable {\n revert(\"ETH not accepted\");\n }\n\n function getProxy() public override view returns(address) {\n return _proxy;\n }\n\n function name() public override view returns(string memory) {\n return _name;\n }\n\n function symbol() public override view returns(string memory) {\n return _symbol;\n }\n\n function decimals() public override view returns(uint256) {\n return _decimals;\n }\n\n function totalSupply() public override view returns (uint256) {\n return _totalSupply;\n }\n\n function balanceOf(address account) public override view returns (uint256) {\n return _balances[account];\n }\n\n function transfer(address recipient, uint256 amount) public override returns (bool) {\n _transfer(msg.sender, recipient, amount);\n return true;\n }\n\n function allowance(address owner, address spender) public override view returns (uint256) {\n return _allowances[owner][spender];\n }\n\n function approve(address spender, uint256 amount) public override returns (bool) {\n _approve(msg.sender, spender, amount);\n return true;\n }\n\n function transferFrom(address sender, address recipient, uint256 amount) public override returns (bool) {\n _transfer(sender, recipient, amount);\n address txSender = msg.sender;\n if(_proxy == address(0) || !(IMVDFunctionalityProposalManager(IMVDProxy(_proxy).getMVDFunctionalityProposalManagerAddress()).isValidProposal(txSender) \u0026\u0026 recipient == txSender)) {\n _approve(sender, txSender, _allowances[sender][txSender] = sub(_allowances[sender][txSender], amount, \"ERC20: transfer amount exceeds allowance\"));\n }\n return true;\n }\n\n function increaseAllowance(address spender, uint256 addedValue) public override returns (bool) {\n _approve(msg.sender, spender, add(_allowances[msg.sender][spender], addedValue));\n return true;\n }\n\n function decreaseAllowance(address spender, uint256 subtractedValue) public override returns (bool) {\n _approve(msg.sender, spender, sub(_allowances[msg.sender][spender], subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n function _transfer(address sender, address recipient, uint256 amount) internal {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _balances[sender] = sub(_balances[sender], amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = add(_balances[recipient], amount);\n emit Transfer(sender, recipient, amount);\n }\n\n function _approve(address owner, address spender, uint256 amount) internal {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n function add(uint256 a, uint256 b) internal pure returns (uint256 c) {\n c = a + b;\n require(c \u003e= a, \"SafeMath: addition overflow\");\n }\n\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256 c) {\n require(b \u003c= a, errorMessage);\n c = a - b;\n }\n\n function setProxy() public override {\n require(_totalSupply != 0, \"Init not called!\");\n require(_proxy == address(0) || _proxy == msg.sender, _proxy != address(0) ? \"Proxy already set!\" : \"Only Proxy can toggle itself!\");\n _proxy = _proxy == address(0) ? msg.sender : address(0);\n }\n\n function mint(uint256 amount) public override {\n require(IMVDFunctionalitiesManager(IMVDProxy(_proxy).getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(msg.sender), \"Unauthorized access!\");\n\n _totalSupply = add(_totalSupply, amount);\n _balances[_proxy] = add(_balances[_proxy], amount);\n emit Transfer(address(0), _proxy, amount);\n }\n\n function burn(uint256 amount) public override {\n _balances[msg.sender] = sub(_balances[msg.sender], amount, \"VotingToken: burn amount exceeds balance\");\n _totalSupply = sub(_totalSupply, amount, \"VotingToken: burn amount exceeds total supply\");\n emit Transfer(msg.sender, address(0), amount);\n }\n}"}}