@luckyfinance/core
Version:
Core contracts for the LuckySwap protocol
38 lines • 62.3 kB
JSON
{
"language": "Solidity",
"sources": {
"contracts/interfaces/IGoldMiner.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\n\ninterface IGoldMiner {\n using BoringERC20 for IERC20;\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided.\n uint256 rewardDebt; // Reward debt. See explanation below.\n }\n\n struct PoolInfo {\n IERC20 lpToken; // Address of LP token contract.\n uint256 allocPoint; // How many allocation points assigned to this pool. GOLN to distribute per block.\n uint256 lastRewardBlock; // Last block number that GOLN distribution occurs.\n uint256 accGoldNuggetPerShare; // Accumulated GOLN per share, times 1e12. See below.\n }\n\n function poolInfo(uint256 pid) external view returns (IGoldMiner.PoolInfo memory);\n function totalAllocPoint() external view returns (uint256);\n function deposit(uint256 _pid, uint256 _amount) external;\n}\n"
},
"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity 0.6.12;\n\nimport \"../interfaces/IERC20.sol\";\n\nlibrary BoringERC20 {\n function safeSymbol(IERC20 token) internal view returns(string memory) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x95d89b41));\n return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\n }\n\n function safeName(IERC20 token) internal view returns(string memory) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x06fdde03));\n return success && data.length > 0 ? abi.decode(data, (string)) : \"???\";\n }\n\n function safeDecimals(IERC20 token) internal view returns (uint8) {\n (bool success, bytes memory data) = address(token).staticcall(abi.encodeWithSelector(0x313ce567));\n return success && data.length == 32 ? abi.decode(data, (uint8)) : 18;\n }\n\n function safeTransfer(IERC20 token, address to, uint256 amount) internal {\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0xa9059cbb, to, amount));\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: Transfer failed\");\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 amount) internal {\n (bool success, bytes memory data) = address(token).call(abi.encodeWithSelector(0x23b872dd, from, to, amount));\n require(success && (data.length == 0 || abi.decode(data, (bool))), \"BoringERC20: TransferFrom failed\");\n }\n}"
},
"@boringcrypto/boring-solidity/contracts/interfaces/IERC20.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\ninterface IERC20 {\n function totalSupply() external view returns (uint256);\n function balanceOf(address account) external view returns (uint256);\n function allowance(address owner, address spender) external view returns (uint256);\n function approve(address spender, uint256 amount) external returns (bool);\n event Transfer(address indexed from, address indexed to, uint256 value);\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n // EIP 2612\n function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n}"
},
"contracts/MiniMinerV2.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"./libraries/SignedSafeMath.sol\";\nimport \"./interfaces/IRewarder.sol\";\nimport \"./interfaces/IGoldMiner.sol\";\n\ninterface IMigratorMiner {\n // Take the current LP token address and return the new LP token address.\n // Migrator should have full access to the caller's LP token.\n function migrate(IERC20 token) external returns (IERC20);\n}\n\n/// @notice The (older) GoldMiner contract gives out a constant number of GOLN tokens per block.\n/// It is the only address with minting rights for GOLN.\n/// The idea for this GoldMiner V2 (MCV2) contract is therefore to be the owner of a dummy token\n/// that is deposited into the GoldMiner V1 (MCV1) contract.\n/// The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.\ncontract MiniMinerV2 is BoringOwnable, BoringBatchable {\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n using BoringERC20 for IERC20;\n using SignedSafeMath for int256;\n\n /// @notice Info of each MCV2 user.\n /// `amount` LP token amount the user has provided.\n /// `rewardDebt` The amount of GOLN entitled to the user.\n struct UserInfo {\n uint256 amount;\n int256 rewardDebt;\n }\n\n /// @notice Info of each MCV2 pool.\n /// `allocPoint` The amount of allocation points assigned to the pool.\n /// Also known as the amount of GOLN to distribute per block.\n struct PoolInfo {\n uint128 accGoldNuggetPerShare;\n uint64 lastRewardTime;\n uint64 allocPoint;\n }\n\n /// @notice Address of GOLN contract.\n IERC20 public immutable GOLN;\n // @notice The migrator contract. It has a lot of power. Can only be set through governance (owner).\n IMigratorMiner public migrator;\n\n /// @notice Info of each MCV2 pool.\n PoolInfo[] public poolInfo;\n /// @notice Address of the LP token for each MCV2 pool.\n IERC20[] public lpToken;\n /// @notice Address of each `IRewarder` contract in MCV2.\n IRewarder[] public rewarder;\n\n /// @notice Info of each user that stakes LP tokens.\n mapping (uint256 => mapping (address => UserInfo)) public userInfo;\n /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n uint256 public totalAllocPoint;\n\n uint256 public goldnuggetPerSecond;\n uint256 private constant ACC_GOLN_PRECISION = 1e12;\n\n event Deposit(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n event Withdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n event Harvest(address indexed user, uint256 indexed pid, uint256 amount);\n event LogPoolAddition(uint256 indexed pid, uint256 allocPoint, IERC20 indexed lpToken, IRewarder indexed rewarder);\n event LogSetPool(uint256 indexed pid, uint256 allocPoint, IRewarder indexed rewarder, bool overwrite);\n event LogUpdatePool(uint256 indexed pid, uint64 lastRewardTime, uint256 lpSupply, uint256 accGoldNuggetPerShare);\n event LogGoldNuggetPerSecond(uint256 goldnuggetPerSecond);\n\n /// @param _goldnugget The GOLN token contract address.\n constructor(IERC20 _goldnugget) public {\n GOLN = _goldnugget;\n }\n\n /// @notice Returns the number of MCV2 pools.\n function poolLength() public view returns (uint256 pools) {\n pools = poolInfo.length;\n }\n\n /// @notice Add a new LP to the pool. Can only be called by the owner.\n /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n /// @param allocPoint AP of the new pool.\n /// @param _lpToken Address of the LP ERC-20 token.\n /// @param _rewarder Address of the rewarder delegate.\n function add(uint256 allocPoint, IERC20 _lpToken, IRewarder _rewarder) public onlyOwner {\n totalAllocPoint = totalAllocPoint.add(allocPoint);\n lpToken.push(_lpToken);\n rewarder.push(_rewarder);\n\n poolInfo.push(PoolInfo({\n allocPoint: allocPoint.to64(),\n lastRewardTime: block.timestamp.to64(),\n accGoldNuggetPerShare: 0\n }));\n emit LogPoolAddition(lpToken.length.sub(1), allocPoint, _lpToken, _rewarder);\n }\n\n /// @notice Update the given pool's GOLN allocation point and `IRewarder` contract. Can only be called by the owner.\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _allocPoint New AP of the pool.\n /// @param _rewarder Address of the rewarder delegate.\n /// @param overwrite True if _rewarder should be `set`. Otherwise `_rewarder` is ignored.\n function set(uint256 _pid, uint256 _allocPoint, IRewarder _rewarder, bool overwrite) public onlyOwner {\n totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n poolInfo[_pid].allocPoint = _allocPoint.to64();\n if (overwrite) { rewarder[_pid] = _rewarder; }\n emit LogSetPool(_pid, _allocPoint, overwrite ? _rewarder : rewarder[_pid], overwrite);\n }\n\n /// @notice Sets the goldnugget per second to be distributed. Can only be called by the owner.\n /// @param _goldnuggetPerSecond The amount of GoldNugget to be distributed per second.\n function setGoldNuggetPerSecond(uint256 _goldnuggetPerSecond) public onlyOwner {\n goldnuggetPerSecond = _goldnuggetPerSecond;\n emit LogGoldNuggetPerSecond(_goldnuggetPerSecond);\n }\n\n /// @notice Set the `migrator` contract. Can only be called by the owner.\n /// @param _migrator The contract address to set.\n function setMigrator(IMigratorMiner _migrator) public onlyOwner {\n migrator = _migrator;\n }\n\n /// @notice Migrate LP token to another LP contract through the `migrator` contract.\n /// @param _pid The index of the pool. See `poolInfo`.\n function migrate(uint256 _pid) public {\n require(address(migrator) != address(0), \"GoldMinerV2: no migrator set\");\n IERC20 _lpToken = lpToken[_pid];\n uint256 bal = _lpToken.balanceOf(address(this));\n _lpToken.approve(address(migrator), bal);\n IERC20 newLpToken = migrator.migrate(_lpToken);\n require(bal == newLpToken.balanceOf(address(this)), \"GoldMinerV2: migrated balance must match\");\n lpToken[_pid] = newLpToken;\n }\n\n /// @notice View function to see pending GOLN on frontend.\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _user Address of user.\n /// @return pending GOLN reward for a given user.\n function pendingGoldNugget(uint256 _pid, address _user) external view returns (uint256 pending) {\n PoolInfo memory pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][_user];\n uint256 accGoldNuggetPerShare = pool.accGoldNuggetPerShare;\n uint256 lpSupply = lpToken[_pid].balanceOf(address(this));\n if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\n uint256 goldnuggetReward = time.mul(goldnuggetPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n accGoldNuggetPerShare = accGoldNuggetPerShare.add(goldnuggetReward.mul(ACC_GOLN_PRECISION) / lpSupply);\n }\n pending = int256(user.amount.mul(accGoldNuggetPerShare) / ACC_GOLN_PRECISION).sub(user.rewardDebt).toUInt256();\n }\n\n /// @notice Update reward variables for all pools. Be careful of gas spending!\n /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n function massUpdatePools(uint256[] calldata pids) external {\n uint256 len = pids.length;\n for (uint256 i = 0; i < len; ++i) {\n updatePool(pids[i]);\n }\n }\n\n /// @notice Update reward variables of the given pool.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @return pool Returns the pool that was updated.\n function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n pool = poolInfo[pid];\n if (block.timestamp > pool.lastRewardTime) {\n uint256 lpSupply = lpToken[pid].balanceOf(address(this));\n if (lpSupply > 0) {\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\n uint256 goldnuggetReward = time.mul(goldnuggetPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n pool.accGoldNuggetPerShare = pool.accGoldNuggetPerShare.add((goldnuggetReward.mul(ACC_GOLN_PRECISION) / lpSupply).to128());\n }\n pool.lastRewardTime = block.timestamp.to64();\n poolInfo[pid] = pool;\n emit LogUpdatePool(pid, pool.lastRewardTime, lpSupply, pool.accGoldNuggetPerShare);\n }\n }\n\n /// @notice Deposit LP tokens to MCV2 for GOLN allocation.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to deposit.\n /// @param to The receiver of `amount` deposit benefit.\n function deposit(uint256 pid, uint256 amount, address to) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][to];\n\n // Effects\n user.amount = user.amount.add(amount);\n user.rewardDebt = user.rewardDebt.add(int256(amount.mul(pool.accGoldNuggetPerShare) / ACC_GOLN_PRECISION));\n\n // Interactions\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onGoldNuggetReward(pid, to, to, 0, user.amount);\n }\n\n lpToken[pid].safeTransferFrom(msg.sender, address(this), amount);\n\n emit Deposit(msg.sender, pid, amount, to);\n }\n\n /// @notice Withdraw LP tokens from MCV2.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to withdraw.\n /// @param to Receiver of the LP tokens.\n function withdraw(uint256 pid, uint256 amount, address to) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][msg.sender];\n\n // Effects\n user.rewardDebt = user.rewardDebt.sub(int256(amount.mul(pool.accGoldNuggetPerShare) / ACC_GOLN_PRECISION));\n user.amount = user.amount.sub(amount);\n\n // Interactions\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onGoldNuggetReward(pid, msg.sender, to, 0, user.amount);\n }\n \n lpToken[pid].safeTransfer(to, amount);\n\n emit Withdraw(msg.sender, pid, amount, to);\n }\n\n /// @notice Harvest proceeds for transaction sender to `to`.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param to Receiver of GOLN rewards.\n function harvest(uint256 pid, address to) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][msg.sender];\n int256 accumulatedGoldNugget = int256(user.amount.mul(pool.accGoldNuggetPerShare) / ACC_GOLN_PRECISION);\n uint256 _pendingGoldNugget = accumulatedGoldNugget.sub(user.rewardDebt).toUInt256();\n\n // Effects\n user.rewardDebt = accumulatedGoldNugget;\n\n // Interactions\n if (_pendingGoldNugget != 0) {\n GOLN.safeTransfer(to, _pendingGoldNugget);\n }\n \n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onGoldNuggetReward( pid, msg.sender, to, _pendingGoldNugget, user.amount);\n }\n\n emit Harvest(msg.sender, pid, _pendingGoldNugget);\n }\n \n /// @notice Withdraw LP tokens from MCV2 and harvest proceeds for transaction sender to `to`.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to withdraw.\n /// @param to Receiver of the LP tokens and GOLN rewards.\n function withdrawAndHarvest(uint256 pid, uint256 amount, address to) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][msg.sender];\n int256 accumulatedGoldNugget = int256(user.amount.mul(pool.accGoldNuggetPerShare) / ACC_GOLN_PRECISION);\n uint256 _pendingGoldNugget = accumulatedGoldNugget.sub(user.rewardDebt).toUInt256();\n\n // Effects\n user.rewardDebt = accumulatedGoldNugget.sub(int256(amount.mul(pool.accGoldNuggetPerShare) / ACC_GOLN_PRECISION));\n user.amount = user.amount.sub(amount);\n \n // Interactions\n GOLN.safeTransfer(to, _pendingGoldNugget);\n\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onGoldNuggetReward(pid, msg.sender, to, _pendingGoldNugget, user.amount);\n }\n\n lpToken[pid].safeTransfer(to, amount);\n\n emit Withdraw(msg.sender, pid, amount, to);\n emit Harvest(msg.sender, pid, _pendingGoldNugget);\n }\n\n /// @notice Withdraw without caring about rewards. EMERGENCY ONLY.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param to Receiver of the LP tokens.\n function emergencyWithdraw(uint256 pid, address to) public {\n UserInfo storage user = userInfo[pid][msg.sender];\n uint256 amount = user.amount;\n user.amount = 0;\n user.rewardDebt = 0;\n\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onGoldNuggetReward(pid, msg.sender, to, 0, 0);\n }\n\n // Note: transfer can fail or succeed if `amount` is zero.\n lpToken[pid].safeTransfer(to, amount);\n emit EmergencyWithdraw(msg.sender, pid, amount, to);\n }\n}\n"
},
"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol": {
"content": "// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n// a library for performing overflow-safe math, updated with awesomeness from of DappHub (https://github.com/dapphub/ds-math)\nlibrary BoringMath {\n function add(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n function sub(uint256 a, uint256 b) internal pure returns (uint256 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {require(b == 0 || (c = a * b)/b == a, \"BoringMath: Mul Overflow\");}\n function to128(uint256 a) internal pure returns (uint128 c) {\n require(a <= uint128(-1), \"BoringMath: uint128 Overflow\");\n c = uint128(a);\n }\n function to64(uint256 a) internal pure returns (uint64 c) {\n require(a <= uint64(-1), \"BoringMath: uint64 Overflow\");\n c = uint64(a);\n }\n function to32(uint256 a) internal pure returns (uint32 c) {\n require(a <= uint32(-1), \"BoringMath: uint32 Overflow\");\n c = uint32(a);\n }\n}\n\nlibrary BoringMath128 {\n function add(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n function sub(uint128 a, uint128 b) internal pure returns (uint128 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n}\n\nlibrary BoringMath64 {\n function add(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n function sub(uint64 a, uint64 b) internal pure returns (uint64 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n}\n\nlibrary BoringMath32 {\n function add(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a + b) >= b, \"BoringMath: Add Overflow\");}\n function sub(uint32 a, uint32 b) internal pure returns (uint32 c) {require((c = a - b) <= a, \"BoringMath: Underflow\");}\n}"
},
"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol": {
"content": "// SPDX-License-Identifier: UNLICENSED\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n\n// P1 - P3: OK\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n// solhint-disable avoid-low-level-calls\n\nimport \"./libraries/BoringERC20.sol\";\n\n// T1 - T4: OK\ncontract BaseBoringBatchable {\n function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {\n // If the _res length is less than 68, then the transaction failed silently (without a revert message)\n if (_returnData.length < 68) return \"Transaction reverted silently\";\n\n assembly {\n // Slice the sighash.\n _returnData := add(_returnData, 0x04)\n }\n return abi.decode(_returnData, (string)); // All that remains is the revert string\n } \n \n // F3 - F9: OK\n // F1: External is ok here because this is the batch function, adding it to a batch makes no sense\n // F2: Calls in the batch may be payable, delegatecall operates in the same context, so each call in the batch has access to msg.value\n // C1 - C21: OK\n // C3: The length of the loop is fully under user control, so can't be exploited\n // C7: Delegatecall is only used on the same contract, so it's safe\n function batch(bytes[] calldata calls, bool revertOnFail) external payable returns(bool[] memory successes, bytes[] memory results) {\n // Interactions\n successes = new bool[](calls.length);\n results = new bytes[](calls.length);\n for (uint256 i = 0; i < calls.length; i++) {\n (bool success, bytes memory result) = address(this).delegatecall(calls[i]);\n require(success || !revertOnFail, _getRevertMsg(result));\n successes[i] = success;\n results[i] = result;\n }\n }\n}\n\n// T1 - T4: OK\ncontract BoringBatchable is BaseBoringBatchable {\n // F1 - F9: OK\n // F6: Parameters can be used front-run the permit and the user's permit will fail (due to nonce or other revert)\n // if part of a batch this could be used to grief once as the second call would not need the permit\n // C1 - C21: OK\n function permitToken(IERC20 token, address from, address to, uint256 amount, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n // Interactions\n // X1 - X5\n token.permit(from, to, amount, deadline, v, r, s);\n }\n}"
},
"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol": {
"content": "// SPDX-License-Identifier: MIT\n// Audit on 5-Jan-2021 by Keno and BoringCrypto\n\n// P1 - P3: OK\npragma solidity 0.6.12;\n\n// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol + Claimable.sol\n// Edited by BoringCrypto\n\n// T1 - T4: OK\ncontract BoringOwnableData {\n // V1 - V5: OK\n address public owner;\n // V1 - V5: OK\n address public pendingOwner;\n}\n\n// T1 - T4: OK\ncontract BoringOwnable is BoringOwnableData {\n // E1: OK\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n constructor () public {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n // F1 - F9: OK\n // C1 - C21: OK\n function transferOwnership(address newOwner, bool direct, bool renounce) public onlyOwner {\n if (direct) {\n // Checks\n require(newOwner != address(0) || renounce, \"Ownable: zero address\");\n\n // Effects\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n pendingOwner = address(0);\n } else {\n // Effects\n pendingOwner = newOwner;\n }\n }\n\n // F1 - F9: OK\n // C1 - C21: OK\n function claimOwnership() public {\n address _pendingOwner = pendingOwner;\n \n // Checks\n require(msg.sender == _pendingOwner, \"Ownable: caller != pending owner\");\n\n // Effects\n emit OwnershipTransferred(owner, _pendingOwner);\n owner = _pendingOwner;\n pendingOwner = address(0);\n }\n\n // M1 - M5: OK\n // C1 - C21: OK\n modifier onlyOwner() {\n require(msg.sender == owner, \"Ownable: caller is not the owner\");\n _;\n }\n}"
},
"contracts/libraries/SignedSafeMath.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\n\nlibrary SignedSafeMath {\n int256 constant private _INT256_MIN = -2**255;\n\n /**\n * @dev Returns the multiplication of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(int256 a, int256 b) internal pure returns (int256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n require(!(a == -1 && b == _INT256_MIN), \"SignedSafeMath: multiplication overflow\");\n\n int256 c = a * b;\n require(c / a == b, \"SignedSafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two signed integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(int256 a, int256 b) internal pure returns (int256) {\n require(b != 0, \"SignedSafeMath: division by zero\");\n require(!(b == -1 && a == _INT256_MIN), \"SignedSafeMath: division overflow\");\n\n int256 c = a / b;\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(int256 a, int256 b) internal pure returns (int256) {\n int256 c = a - b;\n require((b >= 0 && c <= a) || (b < 0 && c > a), \"SignedSafeMath: subtraction overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the addition of two signed integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(int256 a, int256 b) internal pure returns (int256) {\n int256 c = a + b;\n require((b >= 0 && c >= a) || (b < 0 && c < a), \"SignedSafeMath: addition overflow\");\n\n return c;\n }\n\n function toUInt256(int256 a) internal pure returns (uint256) {\n require(a >= 0, \"Integer < 0\");\n return uint256(a);\n }\n}"
},
"contracts/interfaces/IRewarder.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\ninterface IRewarder {\n using BoringERC20 for IERC20;\n function onGoldNuggetReward(uint256 pid, address user, address recipient, uint256 goldnuggetAmount, uint256 newLpAmount) external;\n function pendingTokens(uint256 pid, address user, uint256 goldnuggetAmount) external view returns (IERC20[] memory, uint256[] memory);\n}\n"
},
"contracts/mocks/RewarderMock.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\nimport \"../interfaces/IRewarder.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\n\n\ncontract RewarderMock is IRewarder {\n using BoringMath for uint256;\n using BoringERC20 for IERC20;\n uint256 private immutable rewardMultiplier;\n IERC20 private immutable rewardToken;\n uint256 private constant REWARD_TOKEN_DIVISOR = 1e18;\n address private immutable GOLDMINER_V2;\n\n constructor (uint256 _rewardMultiplier, IERC20 _rewardToken, address _GOLDMINER_V2) public {\n rewardMultiplier = _rewardMultiplier;\n rewardToken = _rewardToken;\n GOLDMINER_V2 = _GOLDMINER_V2;\n }\n\n function onGoldNuggetReward (uint256, address user, address to, uint256 goldnuggetAmount, uint256) onlyMCV2 override external {\n uint256 pendingReward = goldnuggetAmount.mul(rewardMultiplier) / REWARD_TOKEN_DIVISOR;\n uint256 rewardBal = rewardToken.balanceOf(address(this));\n if (pendingReward > rewardBal) {\n rewardToken.safeTransfer(to, rewardBal);\n } else {\n rewardToken.safeTransfer(to, pendingReward);\n }\n }\n \n function pendingTokens(uint256 pid, address user, uint256 goldnuggetAmount) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts) {\n IERC20[] memory _rewardTokens = new IERC20[](1);\n _rewardTokens[0] = (rewardToken);\n uint256[] memory _rewardAmounts = new uint256[](1);\n _rewardAmounts[0] = goldnuggetAmount.mul(rewardMultiplier) / REWARD_TOKEN_DIVISOR;\n return (_rewardTokens, _rewardAmounts);\n }\n\n modifier onlyMCV2 {\n require(\n msg.sender == GOLDMINER_V2,\n \"Only MCV2 can call this function.\"\n );\n _;\n }\n \n}\n"
},
"contracts/mocks/ComplexRewarderTime.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\nimport \"../interfaces/IRewarder.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringERC20.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"../GoldMinerV2.sol\";\n\n/// @author @0xKeno\ncontract ComplexRewarderTime is IRewarder, BoringOwnable{\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n using BoringERC20 for IERC20;\n\n IERC20 private immutable rewardToken;\n\n /// @notice Info of each MCV2 user.\n /// `amount` LP token amount the user has provided.\n /// `rewardDebt` The amount of GOLN entitled to the user.\n struct UserInfo {\n uint256 amount;\n uint256 rewardDebt;\n }\n\n /// @notice Info of each MCV2 pool.\n /// `allocPoint` The amount of allocation points assigned to the pool.\n /// Also known as the amount of GOLN to distribute per block.\n struct PoolInfo {\n uint128 accGoldNuggetPerShare;\n uint64 lastRewardTime;\n uint64 allocPoint;\n }\n\n /// @notice Info of each pool.\n mapping (uint256 => PoolInfo) public poolInfo;\n\n uint256[] public poolIds;\n\n /// @notice Info of each user that stakes LP tokens.\n mapping (uint256 => mapping (address => UserInfo)) public userInfo;\n /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n uint256 totalAllocPoint;\n\n uint256 public rewardPerSecond;\n uint256 private constant ACC_TOKEN_PRECISION = 1e12;\n\n address private immutable GOLDMINER_V2;\n\n event LogOnReward(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n event LogPoolAddition(uint256 indexed pid, uint256 allocPoint);\n event LogSetPool(uint256 indexed pid, uint256 allocPoint);\n event LogUpdatePool(uint256 indexed pid, uint64 lastRewardTime, uint256 lpSupply, uint256 accGoldNuggetPerShare);\n event LogRewardPerSecond(uint256 rewardPerSecond);\n event LogInit();\n\n constructor (IERC20 _rewardToken, uint256 _rewardPerSecond, address _GOLDMINER_V2) public {\n rewardToken = _rewardToken;\n rewardPerSecond = _rewardPerSecond;\n GOLDMINER_V2 = _GOLDMINER_V2;\n }\n\n\n function onGoldNuggetReward (uint256 pid, address _user, address to, uint256, uint256 lpToken) onlyMCV2 override external {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][_user];\n uint256 pending;\n if (user.amount > 0) {\n pending =\n (user.amount.mul(pool.accGoldNuggetPerShare) / ACC_TOKEN_PRECISION).sub(\n user.rewardDebt\n );\n rewardToken.safeTransfer(to, pending);\n }\n user.amount = lpToken;\n user.rewardDebt = lpToken.mul(pool.accGoldNuggetPerShare) / ACC_TOKEN_PRECISION;\n emit LogOnReward(_user, pid, pending, to);\n }\n \n function pendingTokens(uint256 pid, address user, uint256) override external view returns (IERC20[] memory rewardTokens, uint256[] memory rewardAmounts) {\n IERC20[] memory _rewardTokens = new IERC20[](1);\n _rewardTokens[0] = (rewardToken);\n uint256[] memory _rewardAmounts = new uint256[](1);\n _rewardAmounts[0] = pendingToken(pid, user);\n return (_rewardTokens, _rewardAmounts);\n }\n\n /// @notice Sets the goldnugget per second to be distributed. Can only be called by the owner.\n /// @param _rewardPerSecond The amount of GoldNugget to be distributed per second.\n function setRewardPerSecond(uint256 _rewardPerSecond) public onlyOwner {\n rewardPerSecond = _rewardPerSecond;\n emit LogRewardPerSecond(_rewardPerSecond);\n }\n\n modifier onlyMCV2 {\n require(\n msg.sender == GOLDMINER_V2,\n \"Only MCV2 can call this function.\"\n );\n _;\n }\n\n /// @notice Returns the number of MCV2 pools.\n function poolLength() public view returns (uint256 pools) {\n pools = poolIds.length;\n }\n\n /// @notice Add a new LP to the pool. Can only be called by the owner.\n /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n /// @param allocPoint AP of the new pool.\n /// @param _pid Pid on MCV2\n function add(uint256 allocPoint, uint256 _pid) public onlyOwner {\n require(poolInfo[_pid].lastRewardTime == 0, \"Pool already exists\");\n uint256 lastRewardTime = block.timestamp;\n totalAllocPoint = totalAllocPoint.add(allocPoint);\n\n poolInfo[_pid] = PoolInfo({\n allocPoint: allocPoint.to64(),\n lastRewardTime: lastRewardTime.to64(),\n accGoldNuggetPerShare: 0\n });\n poolIds.push(_pid);\n emit LogPoolAddition(_pid, allocPoint);\n }\n\n /// @notice Update the given pool's GOLN allocation point and `IRewarder` contract. Can only be called by the owner.\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _allocPoint New AP of the pool.\n function set(uint256 _pid, uint256 _allocPoint) public onlyOwner {\n totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n poolInfo[_pid].allocPoint = _allocPoint.to64();\n emit LogSetPool(_pid, _allocPoint);\n }\n\n /// @notice View function to see pending Token\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _user Address of user.\n /// @return pending GOLN reward for a given user.\n function pendingToken(uint256 _pid, address _user) public view returns (uint256 pending) {\n PoolInfo memory pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][_user];\n uint256 accGoldNuggetPerShare = pool.accGoldNuggetPerShare;\n uint256 lpSupply = GoldMinerV2(GOLDMINER_V2).lpToken(_pid).balanceOf(GOLDMINER_V2);\n if (block.timestamp > pool.lastRewardTime && lpSupply != 0) {\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\n uint256 goldnuggetReward = time.mul(rewardPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n accGoldNuggetPerShare = accGoldNuggetPerShare.add(goldnuggetReward.mul(ACC_TOKEN_PRECISION) / lpSupply);\n }\n pending = (user.amount.mul(accGoldNuggetPerShare) / ACC_TOKEN_PRECISION).sub(user.rewardDebt);\n }\n\n /// @notice Update reward variables for all pools. Be careful of gas spending!\n /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n function massUpdatePools(uint256[] calldata pids) external {\n uint256 len = pids.length;\n for (uint256 i = 0; i < len; ++i) {\n updatePool(pids[i]);\n }\n }\n\n /// @notice Update reward variables of the given pool.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @return pool Returns the pool that was updated.\n function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n pool = poolInfo[pid];\n if (block.timestamp > pool.lastRewardTime) {\n uint256 lpSupply = GoldMinerV2(GOLDMINER_V2).lpToken(pid).balanceOf(GOLDMINER_V2);\n\n if (lpSupply > 0) {\n uint256 time = block.timestamp.sub(pool.lastRewardTime);\n uint256 goldnuggetReward = time.mul(rewardPerSecond).mul(pool.allocPoint) / totalAllocPoint;\n pool.accGoldNuggetPerShare = pool.accGoldNuggetPerShare.add((goldnuggetReward.mul(ACC_TOKEN_PRECISION) / lpSupply).to128());\n }\n pool.lastRewardTime = block.timestamp.to64();\n poolInfo[pid] = pool;\n emit LogUpdatePool(pid, pool.lastRewardTime, lpSupply, pool.accGoldNuggetPerShare);\n }\n }\n\n}\n"
},
"contracts/GoldMinerV2.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\nimport \"@boringcrypto/boring-solidity/contracts/libraries/BoringMath.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringBatchable.sol\";\nimport \"@boringcrypto/boring-solidity/contracts/BoringOwnable.sol\";\nimport \"./libraries/SignedSafeMath.sol\";\nimport \"./interfaces/IRewarder.sol\";\nimport \"./interfaces/IGoldMiner.sol\";\n\ninterface IMigratorMiner {\n // Take the current LP token address and return the new LP token address.\n // Migrator should have full access to the caller's LP token.\n function migrate(IERC20 token) external returns (IERC20);\n}\n\n/// @notice The (older) GoldMiner contract gives out a constant number of GOLN tokens per block.\n/// It is the only address with minting rights for GOLN.\n/// The idea for this GoldMiner V2 (MCV2) contract is therefore to be the owner of a dummy token\n/// that is deposited into the GoldMiner V1 (MCV1) contract.\n/// The allocation point for this pool on MCV1 is the total allocation point for all pools that receive double incentives.\ncontract GoldMinerV2 is BoringOwnable, BoringBatchable {\n using BoringMath for uint256;\n using BoringMath128 for uint128;\n using BoringERC20 for IERC20;\n using SignedSafeMath for int256;\n\n /// @notice Info of each MCV2 user.\n /// `amount` LP token amount the user has provided.\n /// `rewardDebt` The amount of GOLN entitled to the user.\n struct UserInfo {\n uint256 amount;\n int256 rewardDebt;\n }\n\n /// @notice Info of each MCV2 pool.\n /// `allocPoint` The amount of allocation points assigned to the pool.\n /// Also known as the amount of GOLN to distribute per block.\n struct PoolInfo {\n uint128 accGoldNuggetPerShare;\n uint64 lastRewardBlock;\n uint64 allocPoint;\n }\n\n /// @notice Address of MCV1 contract.\n IGoldMiner public immutable GOLD_MINER;\n /// @notice Address of GOLN contract.\n IERC20 public immutable GOLN;\n /// @notice The index of MCV2 master pool in MCV1.\n uint256 public immutable GOLD_PID;\n // @notice The migrator contract. It has a lot of power. Can only be set through governance (owner).\n IMigratorMiner public migrator;\n\n /// @notice Info of each MCV2 pool.\n PoolInfo[] public poolInfo;\n /// @notice Address of the LP token for each MCV2 pool.\n IERC20[] public lpToken;\n /// @notice Address of each `IRewarder` contract in MCV2.\n IRewarder[] public rewarder;\n\n /// @notice Info of each user that stakes LP tokens.\n mapping (uint256 => mapping (address => UserInfo)) public userInfo;\n /// @dev Total allocation points. Must be the sum of all allocation points in all pools.\n uint256 public totalAllocPoint;\n\n uint256 private constant GOLDMINER_GOLN_PER_BLOCK = 1e20;\n uint256 private constant ACC_GOLN_PRECISION = 1e12;\n\n event Deposit(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n event Withdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n event EmergencyWithdraw(address indexed user, uint256 indexed pid, uint256 amount, address indexed to);\n event Harvest(address indexed user, uint256 indexed pid, uint256 amount);\n event LogPoolAddition(uint256 indexed pid, uint256 allocPoint, IERC20 indexed lpToken, IRewarder indexed rewarder);\n event LogSetPool(uint256 indexed pid, uint256 allocPoint, IRewarder indexed rewarder, bool overwrite);\n event LogUpdatePool(uint256 indexed pid, uint64 lastRewardBlock, uint256 lpSupply, uint256 accGoldNuggetPerShare);\n event LogInit();\n\n /// @param _GOLD_MINER The LuckySwap MCV1 contract address.\n /// @param _goldnugget The GOLN token contract address.\n /// @param _GOLD_PID The pool ID of the dummy token on the base MCV1 contract.\n constructor(IGoldMiner _GOLD_MINER, IERC20 _goldnugget, uint256 _GOLD_PID) public {\n GOLD_MINER = _GOLD_MINER;\n GOLN = _goldnugget;\n GOLD_PID = _GOLD_PID;\n }\n\n /// @notice Deposits a dummy token to `GOLD_MINER` MCV1. This is required because MCV1 holds the minting rights for GOLN.\n /// Any balance of transaction sender in `dummyToken` is transferred.\n /// The allocation point for the pool on MCV1 is the total allocation point for all pools that receive double incentives.\n /// @param dummyToken The address of the ERC-20 token to deposit into MCV1.\n function init(IERC20 dummyToken) external {\n uint256 balance = dummyToken.balanceOf(msg.sender);\n require(balance != 0, \"GoldMinerV2: Balance must exceed 0\");\n dummyToken.safeTransferFrom(msg.sender, address(this), balance);\n dummyToken.approve(address(GOLD_MINER), balance);\n GOLD_MINER.deposit(GOLD_PID, balance);\n emit LogInit();\n }\n\n /// @notice Returns the number of MCV2 pools.\n function poolLength() public view returns (uint256 pools) {\n pools = poolInfo.length;\n }\n\n /// @notice Add a new LP to the pool. Can only be called by the owner.\n /// DO NOT add the same LP token more than once. Rewards will be messed up if you do.\n /// @param allocPoint AP of the new pool.\n /// @param _lpToken Address of the LP ERC-20 token.\n /// @param _rewarder Address of the rewarder delegate.\n function add(uint256 allocPoint, IERC20 _lpToken, IRewarder _rewarder) public onlyOwner {\n uint256 lastRewardBlock = block.number;\n totalAllocPoint = totalAllocPoint.add(allocPoint);\n lpToken.push(_lpToken);\n rewarder.push(_rewarder);\n\n poolInfo.push(PoolInfo({\n allocPoint: allocPoint.to64(),\n lastRewardBlock: lastRewardBlock.to64(),\n accGoldNuggetPerShare: 0\n }));\n emit LogPoolAddition(lpToken.length.sub(1), allocPoint, _lpToken, _rewarder);\n }\n\n /// @notice Update the given pool's GOLN allocation point and `IRewarder` contract. Can only be called by the owner.\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _allocPoint New AP of the pool.\n /// @param _rewarder Address of the rewarder delegate.\n /// @param overwrite True if _rewarder should be `set`. Otherwise `_rewarder` is ignored.\n function set(uint256 _pid, uint256 _allocPoint, IRewarder _rewarder, bool overwrite) public onlyOwner {\n totalAllocPoint = totalAllocPoint.sub(poolInfo[_pid].allocPoint).add(_allocPoint);\n poolInfo[_pid].allocPoint = _allocPoint.to64();\n if (overwrite) { rewarder[_pid] = _rewarder; }\n emit LogSetPool(_pid, _allocPoint, overwrite ? _rewarder : rewarder[_pid], overwrite);\n }\n\n /// @notice Set the `migrator` contract. Can only be called by the owner.\n /// @param _migrator The contract address to set.\n function setMigrator(IMigratorMiner _migrator) public onlyOwner {\n migrator = _migrator;\n }\n\n /// @notice Migrate LP token to another LP contract through the `migrator` contract.\n /// @param _pid The index of the pool. See `poolInfo`.\n function migrate(uint256 _pid) public {\n require(address(migrator) != address(0), \"GoldMinerV2: no migrator set\");\n IERC20 _lpToken = lpToken[_pid];\n uint256 bal = _lpToken.balanceOf(address(this));\n _lpToken.approve(address(migrator), bal);\n IERC20 newLpToken = migrator.migrate(_lpToken);\n require(bal == newLpToken.balanceOf(address(this)), \"GoldMinerV2: migrated balance must match\");\n lpToken[_pid] = newLpToken;\n }\n\n /// @notice View function to see pending GOLN on frontend.\n /// @param _pid The index of the pool. See `poolInfo`.\n /// @param _user Address of user.\n /// @return pending GOLN reward for a given user.\n function pendingGoldNugget(uint256 _pid, address _user) external view returns (uint256 pending) {\n PoolInfo memory pool = poolInfo[_pid];\n UserInfo storage user = userInfo[_pid][_user];\n uint256 accGoldNuggetPerShare = pool.accGoldNuggetPerShare;\n uint256 lpSupply = lpToken[_pid].balanceOf(address(this));\n if (block.number > pool.lastRewardBlock && lpSupply != 0) {\n uint256 blocks = block.number.sub(pool.lastRewardBlock);\n uint256 goldnuggetReward = blocks.mul(goldnuggetPerBlock()).mul(pool.allocPoint) / totalAllocPoint;\n accGoldNuggetPerShare = accGoldNuggetPerShare.add(goldnuggetReward.mul(ACC_GOLN_PRECISION) / lpSupply);\n }\n pending = int256(user.amount.mul(accGoldNuggetPerShare) / ACC_GOLN_PRECISION).sub(user.rewardDebt).toUInt256();\n }\n\n /// @notice Update reward variables for all pools. Be careful of gas spending!\n /// @param pids Pool IDs of all to be updated. Make sure to update all active pools.\n function massUpdatePools(uint256[] calldata pids) external {\n uint256 len = pids.length;\n for (uint256 i = 0; i < len; ++i) {\n updatePool(pids[i]);\n }\n }\n\n /// @notice Calculates and returns the `amount` of GOLN per block.\n function goldnuggetPerBlock() public view returns (uint256 amount) {\n amount = uint256(GOLDMINER_GOLN_PER_BLOCK)\n .mul(GOLD_MINER.poolInfo(GOLD_PID).allocPoint) / GOLD_MINER.totalAllocPoint();\n }\n\n /// @notice Update reward variables of the given pool.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @return pool Returns the pool that was updated.\n function updatePool(uint256 pid) public returns (PoolInfo memory pool) {\n pool = poolInfo[pid];\n if (block.number > pool.lastRewardBlock) {\n uint256 lpSupply = lpToken[pid].balanceOf(address(this));\n if (lpSupply > 0) {\n uint256 blocks = block.number.sub(pool.lastRewardBlock);\n uint256 goldnuggetReward = blocks.mul(goldnuggetPerBlock()).mul(pool.allocPoint) / totalAllocPoint;\n pool.accGoldNuggetPerShare = pool.accGoldNuggetPerShare.add((goldnuggetReward.mul(ACC_GOLN_PRECISION) / lpSupply).to128());\n }\n pool.lastRewardBlock = block.number.to64();\n poolInfo[pid] = pool;\n emit LogUpdatePool(pid, pool.lastRewardBlock, lpSupply, pool.accGoldNuggetPerShare);\n }\n }\n\n /// @notice Deposit LP tokens to MCV2 for GOLN allocation.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to deposit.\n /// @param to The receiver of `amount` deposit benefit.\n function deposit(uint256 pid, uint256 amount, address to) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][to];\n\n // Effects\n user.amount = user.amount.add(amount);\n user.rewardDebt = user.rewardDebt.add(int256(amount.mul(pool.accGoldNuggetPerShare) / ACC_GOLN_PRECISION));\n\n // Interactions\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n _rewarder.onGoldNuggetReward(pid, to, to, 0, user.amount);\n }\n\n lpToken[pid].safeTransferFrom(msg.sender, address(this), amount);\n\n emit Deposit(msg.sender, pid, amount, to);\n }\n\n /// @notice Withdraw LP tokens from MCV2.\n /// @param pid The index of the pool. See `poolInfo`.\n /// @param amount LP token amount to withdraw.\n /// @param to Receiver of the LP tokens.\n function withdraw(uint256 pid, uint256 amount, address to) public {\n PoolInfo memory pool = updatePool(pid);\n UserInfo storage user = userInfo[pid][msg.sender];\n\n // Effects\n user.rewardDebt = user.rewardDebt.sub(int256(amount.mul(pool.accGoldNuggetPerShare) / ACC_GOLN_PRECISION));\n user.amount = user.amount.sub(amount);\n\n // Interactions\n IRewarder _rewarder = rewarder[pid];\n if (address(_rewarder) != address(0)) {\n