Address Contract Verified
Address
0x00A7BA8Ae7bca0B10A32Ea1f8e2a1Da980c6CAd2
Balance
0 ETH
Nonce
1
Code Size
7208 bytes
Creator
0x0B7918e2...c740 at tx 0x331620f5...4d94ac
Indexed Transactions
0
Contract Bytecode
7208 bytes
0x608060405234801561001057600080fd5b506004361061021b5760003560e01c80636c8bcee811610125578063a694fc3a116100ad578063d55a23f41161007c578063d55a23f4146104e3578063df136d65146104eb578063ebe2b12b146104f3578063f1068454146104fb578063f7c618c1146105035761021b565b8063a694fc3a14610491578063c32e7202146104ae578063c8f33c91146104d3578063cd3daf9d146104db5761021b565b80637b0a47ee116100f45780637b0a47ee1461044b57806380faa57d146104535780638b8763471461045b5780638dcb406114610481578063901a7d53146104895761021b565b80636c8bcee8146103e75780637050ccd9146103ef57806370a082311461041d57806372f702f3146104435761021b565b806338d07436116101a857806349f039a21161017757806349f039a214610375578063570ca73514610394578063590a41f51461039c5780635e43c47b146103b957806363d38c3b146103df5761021b565b806338d07436146103235780633d18b912146103485780633e8b83e31461035057806340c35446146103585761021b565b80630fb5a6b4116101ef5780630fb5a6b4146102ac57806318160ddd146102b45780631c1c6fe5146102bc578063262d3d6d146102db5780632ee40908146102e35761021b565b80628cc262146102205780630569d388146102585780630700037d146102625780630f4ef8a614610288575b600080fd5b6102466004803603602081101561023657600080fd5b50356001600160a01b031661050b565b60408051918252519081900360200190f35b61026061057b565b005b6102466004803603602081101561027857600080fd5b50356001600160a01b03166105f4565b610290610606565b604080516001600160a01b039092168252519081900360200190f35b61024661062a565b610246610631565b610260600480360360208110156102d257600080fd5b50351515610638565b610246610656565b61030f600480360360408110156102f957600080fd5b506001600160a01b03813516906020013561065c565b604080519115158252519081900360200190f35b61030f6004803603604081101561033957600080fd5b508035906020013515156106e6565b61030f610929565b61026061093e565b6102906004803603602081101561036e57600080fd5b5035610969565b6102606004803603602081101561038b57600080fd5b50351515610990565b6102906109aa565b61030f600480360360208110156103b257600080fd5b50356109ce565b61030f600480360360208110156103cf57600080fd5b50356001600160a01b0316610ad0565b610246610bf0565b610246610bf6565b61030f6004803603604081101561040557600080fd5b506001600160a01b0381351690602001351515610bfc565b6102466004803603602081101561043357600080fd5b50356001600160a01b0316610e4c565b610290610e67565b610246610e8b565b610246610e91565b6102466004803603602081101561047157600080fd5b50356001600160a01b0316610ea4565b61030f610eb6565b610246610f66565b61030f600480360360208110156104a757600080fd5b5035610f6c565b61030f600480360360408110156104c457600080fd5b50803590602001351515610feb565b610246611015565b61024661101b565b610246611069565b61024661106f565b610246611075565b61024661107b565b61029061109f565b6001600160a01b0381166000908152600960209081526040808320546008909252822054610573919061056d90670de0b6b3a764000090610567906105589061055261101b565b906110c3565b61056188610e4c565b90611120565b90611180565b906111e7565b90505b919050565b336001600160a01b037f000000000000000000000000bc8d9caf4b6bf34773976c5707ad1f2778332dca16146105e6576040805162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b604482015290519081900360640190fd5b6105f2600b6000611b47565b565b60096020526000908152604090205481565b7f000000000000000000000000bc8d9caf4b6bf34773976c5707ad1f2778332dca81565b62093a8081565b6007545b90565b336000908152600a602052604090205461065290826106e6565b5050565b60065481565b60006106688284611241565b61069d6001600160a01b037f000000000000000000000000616e8bfa43f920657b3497dbf40d6b1a02d4608d16333085611415565b6040805183815290516001600160a01b038516917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a25060015b92915050565b6000336106f161101b565b6003556106fc610e91565b6002556001600160a01b03811615610743576107178161050b565b6001600160a01b0382166000908152600960209081526040808320939093556003546008909152919020555b60008411610798576040805162461bcd60e51b815260206004820152601e60248201527f526577617264506f6f6c203a2043616e6e6f7420776974686472617720300000604482015290519081900360640190fd5b60005b600b5481101561082b57600b81815481106107b257fe5b60009182526020822001546040805163f3fef3a360e01b81523360048201526024810189905290516001600160a01b039092169263f3fef3a39260448084019382900301818387803b15801561080757600080fd5b505af115801561081b573d6000803e3d6000fd5b50506001909201915061079b9050565b5060075461083990856110c3565b600755336000908152600a602052604090205461085690856110c3565b336000818152600a602052604090209190915561089e907f000000000000000000000000616e8bfa43f920657b3497dbf40d6b1a02d4608d6001600160a01b03169086611475565b60408051858152905133917f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5919081900360200190a282156108e7576108e5336001610bfc565b505b60408051858152905160009133917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35060019392505050565b6000610936336001610bfc565b506001905090565b600054421015801561095257506000600454115b156105f2576109626004546114cc565b6000600455565b600b818154811061097657fe5b6000918252602090912001546001600160a01b0316905081565b336000908152600a60205260409020546106529082610feb565b7f000000000000000000000000a57b8d98dae62b26ec3bcc4a365338157060b23481565b6000336001600160a01b037f000000000000000000000000a57b8d98dae62b26ec3bcc4a365338157060b2341614610a3b576040805162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b604482015290519081900360640190fd5b600454610a499083906111e7565b91506000544210610a6a57610a5d826114cc565b5060006004556001610576565b60008054610a8690610a7f9062093a806110c3565b42906110c3565b60015490915081026000610aa085610567846103e8611120565b905061033e811015610abf57610ab5856114cc565b6000600455610ac5565b60048590555b506001949350505050565b6000336001600160a01b037f000000000000000000000000bc8d9caf4b6bf34773976c5707ad1f2778332dca1614610b3d576040805162461bcd60e51b815260206004820152600b60248201526a08585d5d1a1bdc9a5e995960aa1b604482015290519081900360640190fd5b6001600160a01b038216610b8a576040805162461bcd60e51b815260206004820152600f60248201526e217265776172642073657474696e6760881b604482015290519081900360640190fd5b600b54600c11610b9c57506000610576565b50600b8054600181810183556000929092527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b0384166001600160a01b0319909116179055919050565b60045481565b61033e81565b600082610c0761101b565b600355610c12610e91565b6002556001600160a01b03811615610c5957610c2d8161050b565b6001600160a01b0382166000908152600960209081526040808320939093556003546008909152919020555b6000610c648561050b565b90508015610daa576001600160a01b03808616600090815260096020526040812055610cb3907f000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d168683611475565b7f000000000000000000000000a57b8d98dae62b26ec3bcc4a365338157060b2346001600160a01b03166371192b177f000000000000000000000000000000000000000000000000000000000000000087846040518463ffffffff1660e01b815260040180848152602001836001600160a01b031681526020018281526020019350505050600060405180830381600087803b158015610d5257600080fd5b505af1158015610d66573d6000803e3d6000fd5b50506040805184815290516001600160a01b03891693507fe2403640ba68fed3a2f88b7557551d1993f84b99bb10ff833f0cf8db0c5e048692509081900360200190a25b8315610ac55760005b600b54811015610e4057600b8181548110610dca57fe5b600091825260208220015460408051630c00007b60e41b81526001600160a01b038a811660048301529151919092169263c00007b0926024808201939182900301818387803b158015610e1c57600080fd5b505af1158015610e30573d6000803e3d6000fd5b505060019092019150610db39050565b50506001949350505050565b6001600160a01b03166000908152600a602052604090205490565b7f000000000000000000000000616e8bfa43f920657b3497dbf40d6b1a02d4608d81565b60015481565b6000610e9f426000546115f0565b905090565b60086020526000908152604090205481565b6000807f000000000000000000000000616e8bfa43f920657b3497dbf40d6b1a02d4608d6001600160a01b03166370a08231336040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b158015610f2657600080fd5b505afa158015610f3a573d6000803e3d6000fd5b505050506040513d6020811015610f5057600080fd5b50519050610f5d81610f6c565b50600191505090565b60055481565b6000610f788233611241565b610fad6001600160a01b037f000000000000000000000000616e8bfa43f920657b3497dbf40d6b1a02d4608d16333085611415565b60408051838152905133917f9e71bc8eea02a63969f509818f2dafb9254532904319f9dbda79b67bd34a5f3d919081900360200190a2506001919050565b6000610ff8833333611606565b50811561100c5761100a336001610bfc565b505b50600192915050565b60025481565b6000611025610631565b6110325750600354610635565b610e9f611060611040610631565b610567670de0b6b3a7640000610561600154610561600254610552610e91565b600354906111e7565b600b5490565b60035481565b60005481565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000ba100000625a3754423978a60c9317c58a424e3d81565b60008282111561111a576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008261112f575060006106e0565b8282028284828161113c57fe5b04146111795760405162461bcd60e51b8152600401808060200182810382526021815260200180611ba86021913960400191505060405180910390fd5b9392505050565b60008082116111d6576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b8183816111df57fe5b049392505050565b600082820183811015611179576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b8061124a61101b565b600355611255610e91565b6002556001600160a01b0381161561129c576112708161050b565b6001600160a01b0382166000908152600960209081526040808320939093556003546008909152919020555b600083116112f1576040805162461bcd60e51b815260206004820152601b60248201527f526577617264506f6f6c203a2043616e6e6f74207374616b6520300000000000604482015290519081900360640190fd5b60005b600b5481101561138857600b818154811061130b57fe5b6000918252602082200154604080516356e4bb9760e11b81526001600160a01b038781166004830152602482018990529151919092169263adc9772e926044808201939182900301818387803b15801561136457600080fd5b505af1158015611378573d6000803e3d6000fd5b5050600190920191506112f49050565b5060075461139690846111e7565b6007556001600160a01b0382166000908152600a60205260409020546113bc90846111e7565b6001600160a01b0383166000818152600a602090815260408083209490945583518781529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a3505050565b604080516001600160a01b0380861660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b17905261146f908590611879565b50505050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114c7908490611879565b505050565b60006114d661101b565b6003556114e1610e91565b6002556001600160a01b03811615611528576114fc8161050b565b6001600160a01b0382166000908152600960209081526040808320939093556003546008909152919020555b60065461153590836111e7565b60065560005442106115565761154e8262093a80611180565b60015561159e565b6000805461156490426110c3565b9050600061157d6001548361112090919063ffffffff16565b905061158984826111e7565b93506115988462093a80611180565b60015550505b60058290554260028190556115b69062093a806111e7565b6000556040805183815290517fde88a922e0d3b88b24e9623efeb464919c6bf9f66857a65e2bfcf2ce87a9433d9181900360200190a15050565b60008183106115ff5781611179565b5090919050565b60008261161161101b565b60035561161c610e91565b6002556001600160a01b03811615611663576116378161050b565b6001600160a01b0382166000908152600960209081526040808320939093556003546008909152919020555b60005b600b548110156116fa57600b818154811061167d57fe5b60009182526020822001546040805163f3fef3a360e01b81526001600160a01b038981166004830152602482018b90529151919092169263f3fef3a3926044808201939182900301818387803b1580156116d657600080fd5b505af11580156116ea573d6000803e3d6000fd5b5050600190920191506116669050565b5060075461170890866110c3565b6007556001600160a01b0384166000908152600a602052604090205461172e90866110c3565b6001600160a01b038086166000908152600a60205260408082209390935582516305335c3960e21b81527f0000000000000000000000000000000000000000000000000000000000000000600482015260248101899052868316604482015292517f000000000000000000000000a57b8d98dae62b26ec3bcc4a365338157060b234909216926314cd70e4926064808301939282900301818387803b1580156117d657600080fd5b505af11580156117ea573d6000803e3d6000fd5b50506040805188815290516001600160a01b03881693507f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d592509081900360200190a26040805186815290516000916001600160a01b038716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a3506001949350505050565b60606118ce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661192a9092919063ffffffff16565b8051909150156114c7578080602001905160208110156118ed57600080fd5b50516114c75760405162461bcd60e51b815260040180806020018281038252602a815260200180611bc9602a913960400191505060405180910390fd5b60606119398484600085611941565b949350505050565b6060824710156119825760405162461bcd60e51b8152600401808060200182810382526026815260200180611b826026913960400191505060405180910390fd5b61198b85611a9d565b6119dc576040805162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015290519081900360640190fd5b60006060866001600160a01b031685876040518082805190602001908083835b60208310611a1b5780518252601f1990920191602091820191016119fc565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611a7d576040519150601f19603f3d011682016040523d82523d6000602084013e611a82565b606091505b5091509150611a92828286611aa3565b979650505050505050565b3b151590565b60608315611ab2575081611179565b825115611ac25782518084602001fd5b8160405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611b0c578181015183820152602001611af4565b50505050905090810190601f168015611b395780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5080546000825590600052602060002090810190611b659190611b68565b50565b5b80821115611b7d5760008155600101611b69565b509056fe416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a264697066735822122079549c85f72d2948763d17f7c50c52921444a55c65ba5d5bd9554e33ffc10e8664736f6c634300060c0033
Verified Source Code Full Match
Compiler: v0.6.12+commit.27d51765
EVM: istanbul
Optimization: Yes (200 runs)
SafeMath.sol 214 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.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, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, 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 (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @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) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @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) {
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, reverting 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) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting 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) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* 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);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* 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);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* 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;
}
}
Address.sol 189 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
/**
* @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) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(account) }
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} 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");
require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
IERC20.sol 77 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.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);
}
Interfaces.sol 149 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
interface ICurveGauge {
function deposit(uint256) external;
function balanceOf(address) external view returns (uint256);
function withdraw(uint256) external;
function claim_rewards() external;
function reward_tokens(uint256) external view returns(address);//v2
function rewarded_token() external view returns(address);//v1
function lp_token() external view returns(address);
}
interface ICurveVoteEscrow {
function create_lock(uint256, uint256) external;
function increase_amount(uint256) external;
function increase_unlock_time(uint256) external;
function withdraw() external;
function smart_wallet_checker() external view returns (address);
function commit_smart_wallet_checker(address) external;
function apply_smart_wallet_checker() external;
}
interface IWalletChecker {
function check(address) external view returns (bool);
function approveWallet(address) external;
function dao() external view returns (address);
}
interface IVoting{
function vote(uint256, bool, bool) external; //voteId, support, executeIfDecided
function getVote(uint256) external view returns(bool,bool,uint64,uint64,uint64,uint64,uint256,uint256,uint256,bytes memory);
function vote_for_gauge_weights(address,uint256) external;
}
interface IMinter{
function mint(address) external;
}
interface IStaker{
function deposit(address, address) external returns (bool);
function withdraw(address) external returns (uint256);
function withdraw(address, address, uint256) external returns (bool);
function withdrawAll(address, address) external returns (bool);
function createLock(uint256, uint256) external returns(bool);
function increaseAmount(uint256) external returns(bool);
function increaseTime(uint256) external returns(bool);
function release() external returns(bool);
function claimCrv(address) external returns (uint256);
function claimRewards(address) external returns(bool);
function claimFees(address,address) external returns (uint256);
function setStashAccess(address, bool) external returns (bool);
function vote(uint256,address,bool) external returns(bool);
function voteGaugeWeight(address,uint256) external returns(bool);
function balanceOfPool(address) external view returns (uint256);
function operator() external view returns (address);
function execute(address _to, uint256 _value, bytes calldata _data) external returns (bool, bytes memory);
function setVote(bytes32 hash, bool valid) external;
function migrate(address to) external;
}
interface IRewards{
function stake(address, uint256) external;
function stakeFor(address, uint256) external;
function withdraw(address, uint256) external;
function exit(address) external;
function getReward(address) external;
function queueNewRewards(uint256) external;
function notifyRewardAmount(uint256) external;
function addExtraReward(address) external;
function extraRewardsLength() external view returns (uint256);
function stakingToken() external view returns (address);
function rewardToken() external view returns(address);
function earned(address account) external view returns (uint256);
}
interface IStash{
function stashRewards() external returns (bool);
function processStash() external returns (bool);
function claimRewards() external returns (bool);
function initialize(uint256 _pid, address _operator, address _staker, address _gauge, address _rewardFactory) external;
}
interface IFeeDistributor {
function claimToken(address user, address token) external returns (uint256);
function claimTokens(address user, address[] calldata tokens) external returns (uint256[] memory);
function getTokenTimeCursor(address token) external view returns (uint256);
}
interface ITokenMinter{
function mint(address,uint256) external;
function burn(address,uint256) external;
}
interface IDeposit{
function isShutdown() external view returns(bool);
function balanceOf(address _account) external view returns(uint256);
function totalSupply() external view returns(uint256);
function poolInfo(uint256) external view returns(address,address,address,address,address, bool);
function rewardClaimed(uint256,address,uint256) external;
function withdrawTo(uint256,uint256,address) external;
function claimRewards(uint256,address) external returns(bool);
function rewardArbitrator() external returns(address);
function setGaugeRedirect(uint256 _pid) external returns(bool);
function owner() external returns(address);
function deposit(uint256 _pid, uint256 _amount, bool _stake) external returns(bool);
}
interface ICrvDeposit{
function deposit(uint256, bool) external;
function lockIncentive() external view returns(uint256);
}
interface IRewardFactory{
function setAccess(address,bool) external;
function CreateCrvRewards(uint256,address,address) external returns(address);
function CreateTokenRewards(address,address,address) external returns(address);
function activeRewardCount(address) external view returns(uint256);
function addActiveReward(address,uint256) external returns(bool);
function removeActiveReward(address,uint256) external returns(bool);
}
interface IStashFactory{
function CreateStash(uint256,address,address,uint256) external returns(address);
}
interface ITokenFactory{
function CreateDepositToken(address) external returns(address);
}
interface IPools{
function addPool(address _lptoken, address _gauge, uint256 _stashVersion) external returns(bool);
function forceAddPool(address _lptoken, address _gauge, uint256 _stashVersion) external returns(bool);
function shutdownPool(uint256 _pid) external returns(bool);
function poolInfo(uint256) external view returns(address,address,address,address,address,bool);
function poolLength() external view returns (uint256);
function gaugeMap(address) external view returns(bool);
function setPoolManager(address _poolM) external;
}
interface IVestedEscrow{
function fund(address[] calldata _recipient, uint256[] calldata _amount) external returns(bool);
}
interface IRewardDeposit {
function addReward(address, uint256) external;
}
SafeERC20.sol 75 lines
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using 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");
}
}
}
BaseRewardPool.sol 383 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
/**
*Submitted for verification at Etherscan.io on 2020-07-17
*/
/*
____ __ __ __ _
/ __/__ __ ___ / /_ / / ___ / /_ (_)__ __
_\ \ / // // _ \/ __// _ \/ -_)/ __// / \ \ /
/___/ \_, //_//_/\__//_//_/\__/ \__//_/ /_\_\
/___/
* Synthetix: BaseRewardPool.sol
*
* Docs: https://docs.synthetix.io/
*
*
* MIT License
* ===========
*
* Copyright (c) 2020 Synthetix
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*/
import "./Interfaces.sol";
import "./interfaces/MathUtil.sol";
import "@openzeppelin/contracts-0.6/math/SafeMath.sol";
import "@openzeppelin/contracts-0.6/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts-0.6/utils/Address.sol";
import "@openzeppelin/contracts-0.6/token/ERC20/SafeERC20.sol";
/**
* @title BaseRewardPool
* @author Synthetix -> ConvexFinance
* @notice Unipool rewards contract that is re-deployed from rFactory for each staking pool.
* @dev Changes made here by ConvexFinance are to do with the delayed reward allocation. Curve is queued for
* rewards and the distribution only begins once the new rewards are sufficiently large, or the epoch
* has ended. Additionally, enables hooks for `extraRewards` that can be enabled at any point to
* distribute a child reward token (i.e. a secondary one from Curve, or a seperate one).
*/
contract BaseRewardPool {
using SafeMath for uint256;
using SafeERC20 for IERC20;
IERC20 public immutable rewardToken;
IERC20 public immutable stakingToken;
uint256 public constant duration = 7 days;
address public immutable operator;
address public immutable rewardManager;
uint256 public immutable pid;
uint256 public periodFinish = 0;
uint256 public rewardRate = 0;
uint256 public lastUpdateTime;
uint256 public rewardPerTokenStored;
uint256 public queuedRewards = 0;
uint256 public currentRewards = 0;
uint256 public historicalRewards = 0;
uint256 public constant newRewardRatio = 830;
uint256 private _totalSupply;
mapping(address => uint256) public userRewardPerTokenPaid;
mapping(address => uint256) public rewards;
mapping(address => uint256) private _balances;
address[] public extraRewards;
event RewardAdded(uint256 reward);
event Staked(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event RewardPaid(address indexed user, uint256 reward);
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev This is called directly from RewardFactory
* @param pid_ Effectively the pool identifier - used in the Booster
* @param stakingToken_ Pool LP token
* @param rewardToken_ Crv
* @param operator_ Booster
* @param rewardManager_ RewardFactory
*/
constructor(
uint256 pid_,
address stakingToken_,
address rewardToken_,
address operator_,
address rewardManager_
) public {
pid = pid_;
stakingToken = IERC20(stakingToken_);
rewardToken = IERC20(rewardToken_);
operator = operator_;
rewardManager = rewardManager_;
}
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
function extraRewardsLength() external view returns (uint256) {
return extraRewards.length;
}
function addExtraReward(address _reward) external returns(bool){
require(msg.sender == rewardManager, "!authorized");
require(_reward != address(0),"!reward setting");
if(extraRewards.length >= 12){
return false;
}
extraRewards.push(_reward);
return true;
}
function clearExtraRewards() external{
require(msg.sender == rewardManager, "!authorized");
delete extraRewards;
}
modifier updateReward(address account) {
rewardPerTokenStored = rewardPerToken();
lastUpdateTime = lastTimeRewardApplicable();
if (account != address(0)) {
rewards[account] = earned(account);
userRewardPerTokenPaid[account] = rewardPerTokenStored;
}
_;
}
function lastTimeRewardApplicable() public view returns (uint256) {
return MathUtil.min(block.timestamp, periodFinish);
}
function rewardPerToken() public view returns (uint256) {
if (totalSupply() == 0) {
return rewardPerTokenStored;
}
return
rewardPerTokenStored.add(
lastTimeRewardApplicable()
.sub(lastUpdateTime)
.mul(rewardRate)
.mul(1e18)
.div(totalSupply())
);
}
function earned(address account) public view returns (uint256) {
return
balanceOf(account)
.mul(rewardPerToken().sub(userRewardPerTokenPaid[account]))
.div(1e18)
.add(rewards[account]);
}
function stake(uint256 _amount)
public
returns(bool)
{
_processStake(_amount, msg.sender);
stakingToken.safeTransferFrom(msg.sender, address(this), _amount);
emit Staked(msg.sender, _amount);
return true;
}
function stakeAll() external returns(bool){
uint256 balance = stakingToken.balanceOf(msg.sender);
stake(balance);
return true;
}
function stakeFor(address _for, uint256 _amount)
public
returns(bool)
{
_processStake(_amount, _for);
//take away from sender
stakingToken.safeTransferFrom(msg.sender, address(this), _amount);
emit Staked(_for, _amount);
return true;
}
/**
* @dev Generic internal staking function that basically does 3 things: update rewards based
* on previous balance, trigger also on any child contracts, then update balances.
* @param _amount Units to add to the users balance
* @param _receiver Address of user who will receive the stake
*/
function _processStake(uint256 _amount, address _receiver) internal updateReward(_receiver) {
require(_amount > 0, 'RewardPool : Cannot stake 0');
//also stake to linked rewards
for(uint i=0; i < extraRewards.length; i++){
IRewards(extraRewards[i]).stake(_receiver, _amount);
}
_totalSupply = _totalSupply.add(_amount);
_balances[_receiver] = _balances[_receiver].add(_amount);
emit Transfer(address(0), _receiver, _amount);
}
function withdraw(uint256 amount, bool claim)
public
updateReward(msg.sender)
returns(bool)
{
require(amount > 0, 'RewardPool : Cannot withdraw 0');
//also withdraw from linked rewards
for(uint i=0; i < extraRewards.length; i++){
IRewards(extraRewards[i]).withdraw(msg.sender, amount);
}
_totalSupply = _totalSupply.sub(amount);
_balances[msg.sender] = _balances[msg.sender].sub(amount);
stakingToken.safeTransfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
if(claim){
getReward(msg.sender,true);
}
emit Transfer(msg.sender, address(0), amount);
return true;
}
function withdrawAll(bool claim) external{
withdraw(_balances[msg.sender],claim);
}
function withdrawAndUnwrap(uint256 amount, bool claim) public returns(bool){
_withdrawAndUnwrapTo(amount, msg.sender, msg.sender);
//get rewards too
if(claim){
getReward(msg.sender,true);
}
return true;
}
function _withdrawAndUnwrapTo(uint256 amount, address from, address receiver) internal updateReward(from) returns(bool){
//also withdraw from linked rewards
for(uint i=0; i < extraRewards.length; i++){
IRewards(extraRewards[i]).withdraw(from, amount);
}
_totalSupply = _totalSupply.sub(amount);
_balances[from] = _balances[from].sub(amount);
//tell operator to withdraw from here directly to user
IDeposit(operator).withdrawTo(pid,amount,receiver);
emit Withdrawn(from, amount);
emit Transfer(from, address(0), amount);
return true;
}
function withdrawAllAndUnwrap(bool claim) external{
withdrawAndUnwrap(_balances[msg.sender],claim);
}
/**
* @dev Gives a staker their rewards, with the option of claiming extra rewards
* @param _account Account for which to claim
* @param _claimExtras Get the child rewards too?
*/
function getReward(address _account, bool _claimExtras) public updateReward(_account) returns(bool){
uint256 reward = earned(_account);
if (reward > 0) {
rewards[_account] = 0;
rewardToken.safeTransfer(_account, reward);
IDeposit(operator).rewardClaimed(pid, _account, reward);
emit RewardPaid(_account, reward);
}
//also get rewards from linked rewards
if(_claimExtras){
for(uint i=0; i < extraRewards.length; i++){
IRewards(extraRewards[i]).getReward(_account);
}
}
return true;
}
/**
* @dev Called by a staker to get their allocated rewards
*/
function getReward() external returns(bool){
getReward(msg.sender,true);
return true;
}
/**
* @dev Processes queued rewards in isolation, providing the period has finished.
* This allows a cheaper way to trigger rewards on low value pools.
*/
function processIdleRewards() external {
if (block.timestamp >= periodFinish && queuedRewards > 0) {
notifyRewardAmount(queuedRewards);
queuedRewards = 0;
}
}
/**
* @dev Called by the booster to allocate new Crv rewards to this pool
* Curve is queued for rewards and the distribution only begins once the new rewards are sufficiently
* large, or the epoch has ended.
*/
function queueNewRewards(uint256 _rewards) external returns(bool){
require(msg.sender == operator, "!authorized");
_rewards = _rewards.add(queuedRewards);
if (block.timestamp >= periodFinish) {
notifyRewardAmount(_rewards);
queuedRewards = 0;
return true;
}
//et = now - (finish-duration)
uint256 elapsedTime = block.timestamp.sub(periodFinish.sub(duration));
//current at now: rewardRate * elapsedTime
uint256 currentAtNow = rewardRate * elapsedTime;
uint256 queuedRatio = currentAtNow.mul(1000).div(_rewards);
//uint256 queuedRatio = currentRewards.mul(1000).div(_rewards);
if(queuedRatio < newRewardRatio){
notifyRewardAmount(_rewards);
queuedRewards = 0;
}else{
queuedRewards = _rewards;
}
return true;
}
function notifyRewardAmount(uint256 reward)
internal
updateReward(address(0))
{
historicalRewards = historicalRewards.add(reward);
if (block.timestamp >= periodFinish) {
rewardRate = reward.div(duration);
} else {
uint256 remaining = periodFinish.sub(block.timestamp);
uint256 leftover = remaining.mul(rewardRate);
reward = reward.add(leftover);
rewardRate = reward.div(duration);
}
currentRewards = reward;
lastUpdateTime = block.timestamp;
periodFinish = block.timestamp.add(duration);
emit RewardAdded(reward);
}
}
MathUtil.sol 14 lines
// SPDX-License-Identifier: MIT
pragma solidity 0.6.12;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library MathUtil {
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
}
Read Contract
balanceOf 0x70a08231 → uint256
currentRewards 0x901a7d53 → uint256
duration 0x0fb5a6b4 → uint256
earned 0x008cc262 → uint256
extraRewards 0x40c35446 → address
extraRewardsLength 0xd55a23f4 → uint256
historicalRewards 0x262d3d6d → uint256
lastTimeRewardApplicable 0x80faa57d → uint256
lastUpdateTime 0xc8f33c91 → uint256
newRewardRatio 0x6c8bcee8 → uint256
operator 0x570ca735 → address
periodFinish 0xebe2b12b → uint256
pid 0xf1068454 → uint256
queuedRewards 0x63d38c3b → uint256
rewardManager 0x0f4ef8a6 → address
rewardPerToken 0xcd3daf9d → uint256
rewardPerTokenStored 0xdf136d65 → uint256
rewardRate 0x7b0a47ee → uint256
rewardToken 0xf7c618c1 → address
rewards 0x0700037d → uint256
stakingToken 0x72f702f3 → address
totalSupply 0x18160ddd → uint256
userRewardPerTokenPaid 0x8b876347 → uint256
Write Contract 13 functions
These functions modify contract state and require a wallet transaction to execute.
addExtraReward 0x5e43c47b
address _reward
returns: bool
clearExtraRewards 0x0569d388
No parameters
getReward 0x3d18b912
No parameters
returns: bool
getReward 0x7050ccd9
address _account
bool _claimExtras
returns: bool
processIdleRewards 0x3e8b83e3
No parameters
queueNewRewards 0x590a41f5
uint256 _rewards
returns: bool
stake 0xa694fc3a
uint256 _amount
returns: bool
stakeAll 0x8dcb4061
No parameters
returns: bool
stakeFor 0x2ee40908
address _for
uint256 _amount
returns: bool
withdraw 0x38d07436
uint256 amount
bool claim
returns: bool
withdrawAll 0x1c1c6fe5
bool claim
withdrawAllAndUnwrap 0x49f039a2
bool claim
withdrawAndUnwrap 0xc32e7202
uint256 amount
bool claim
returns: bool
Recent Transactions
No transactions found for this address