A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z | AA | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1 | 1 pragma solidity >=0.4.24 <0.6.0; 2 contract Bar { 3 constructor () public {} 4 function baz(uint p) public pure returns (uint ret) { 5 ret = p + 2; 6 } 7 } 8 contract ExternalFunctionCall { 9 function foo(uint x, Bar y) public pure returns (uint ret) { 10 ret = x + y.baz(2); 11 } 12 function testExternalFunctionCall(uint x) public returns (uint y) { 13 Bar bar = new Bar(); 14 y = this.foo(x, bar); 15 } 16 } | 14+ assert (y == x + 4); | 14+ | assert (y == x + 4); | |||||||||||||||||||||||
2 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 109+ | require(admin == msg.sender, "Ownable: caller is not the owner"); | |||||||||||||||||||||||
3 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 141+ | require(_whitelist[msg.sender] != address(0), "only white"); | |||||||||||||||||||||||
4 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 155+ | require(paths.length == 2,"deposit: PE"); | |||||||||||||||||||||||
5 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 158+ | require(_amount > 0, "deposit: zero"); | |||||||||||||||||||||||
6 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 165+ | require(paths.length == 2,"deposit: PE"); | |||||||||||||||||||||||
7 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 170+ | require(vars.newBalance > vars.oldBalance, "B:E"); | |||||||||||||||||||||||
8 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 171+ | require(vars.liquidity >= _minTokens, "H:S"); | |||||||||||||||||||||||
9 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 191+ | require(overflow == 0, "Exceeding the ticket limit"); | |||||||||||||||||||||||
10 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 223+ | require(overflow == 0, "Please withdraw usdt in advance"); | |||||||||||||||||||||||
11 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 229+ | require(false, "You never staked this ticket before"); | |||||||||||||||||||||||
12 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 242+ | require(user.amount >= _amount, "withdraw: not good"); | |||||||||||||||||||||||
13 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 259+ | require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); | |||||||||||||||||||||||
14 | 1 // SPDX-License-Identifier: MIT 2 pragma experimental ABIEncoderV2; 3 pragma solidity 0.6.12; 4 import "./ParaToken.sol"; 5 import "./interfaces/IERC20.sol"; 6 import "./libraries/SafeERC20.sol"; 7 import "./libraries/EnumerableSet.sol"; 8 import "./libraries/SafeMath_para.sol"; 9 import "./interfaces/IWETH.sol"; 10 import './interfaces/IParaRouter02.sol'; 11 import './interfaces/IParaPair.sol'; 12 import './libraries/TransferHelper.sol'; 13 import './interfaces/IFeeDistributor.sol'; 14 import './ParaProxy.sol'; 15 interface IParaTicket { 16 function level() external pure returns (uint256); 17 function tokensOfOwner(address owner) external view returns (uint256[] memory); 18 function setApprovalForAll(address to, bool approved) external; 19 function safeTransferFrom(address from, address to, uint256 tokenId) external; 20 function setUsed(uint256 tokenId) external; 21 function _used(uint256 tokenId) external view returns(bool); 22 } 23 interface IMigratorChef { 24 function migrate(IERC20 token) external returns (IERC20); 25 } 26 contract MasterChef is ParaProxyAdminStorage { 27 using SafeMath for uint256; 28 using SafeERC20 for IERC20; 29 // Info of each user. 30 struct UserInfo { 31 uint256 amount; // How many LP tokens the user has provided. 32 uint256 rewardDebt; // Reward debt. See explanation below. 33 // 34 // We do some fancy math here. Basically, any point in time, the amount of T42s 35 // entitled to a user but is pending to be distributed is: 36 // 37 // pending reward = (user.amount * pool.accT42PerShare) - user.rewardDebt 38 // 39 // Whenever a user deposits or withdraws LP tokens to a pool. Here's what happens: 40 // 1. The pool's `accT42PerShare` (and `lastRewardBlock`) gets updated. 41 // 2. User receives the pending reward sent to his/her address. 42 // 3. User's `amount` gets updated. 43 // 4. User's `rewardDebt` gets updated. 44 } 45 // Info of each pool. 46 struct PoolInfo { 47 IERC20 lpToken; // Address of LP token contract. 48 uint256 allocPoint; // How many allocation points assigned to this pool. T42s to distribute per block. 49 uint256 lastRewardBlock; // Last block number that T42s distribution occurs. 50 uint256 accT42PerShare; // Accumulated T42s per share, times 1e12. See below. 51 IParaTicket ticket; // if VIP pool, NFT ticket contract, else 0 52 uint256 pooltype; 53 } 54 // every farm's percent of T42 issue 55 uint8[10] public farmPercent; 56 // The T42 TOKEN! 57 ParaToken public t42; 58 // Dev address. 59 address public devaddr; 60 // Treasury address 61 address public treasury; 62 // Fee Distritution contract address 63 address public feeDistributor; 64 // Mining income commission rate, default 5% 65 uint256 public claimFeeRate; 66 // Mining pool withdrawal fee rate, the default is 1.3% 67 uint256 public withdrawFeeRate; 68 // Block number when bonus T42 period ends. 69 uint256 public bonusEndBlock; 70 // Bonus muliplier for early t42 makers. 71 uint256 public constant BONUS_MULTIPLIER = 1; 72 // The migrator contract. It has a lot of power. Can only be set through governance (owner). 73 IMigratorChef public migrator; 74 // Info of each pool. 75 PoolInfo[] public poolInfo; 76 // Info of each user that stakes LP tokens. 77 mapping(uint256 => mapping(address => UserInfo)) public userInfo; 78 // Total allocation poitns. Must be the sum of all allocation points in all pools. 79 uint256 public totalAllocPoint; 80 // The block number when T42 mining starts. 81 uint256 public startBlock; 82 // the address of WETH 83 address public WETH; 84 // the address of Router 85 IParaRouter02 public paraRouter; 86 // Change returned after adding liquidity 87 mapping(address => mapping(address => uint)) public userChange; 88 // record who staked which NFT ticket into this contract 89 mapping(address => mapping(address => uint[])) public ticket_stakes; 90 // record total claimed T42 for per user & per PoolType 91 mapping(address => mapping(uint256 => uint256)) public _totalClaimed; 92 mapping(address => address) public _whitelist; 93 // TOTAL Deposit pid => uint 94 mapping(uint => uint) public poolsTotalDeposit; 95 event Deposit(address indexed user, uint256 indexed pid, uint256 amount); 96 event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); 97 event EmergencyWithdraw( 98 address indexed user, 99 uint256 indexed pid, 100 uint256 amount 101 ); 102 event WithdrawChange( 103 address indexed user, 104 address indexed token, 105 uint256 change); 106 /** 107 * @dev Throws if called by any account other than the owner. 108 */ 109 modifier onlyOwner() { 110 _; 111 } 112 constructor() public { 113 admin = msg.sender; 114 } 115 function initialize( 116 ParaToken _t42, 117 address _treasury, 118 address _feeDistributor, 119 address _devaddr, 120 uint256 _bonusEndBlock, 121 address _WETH, 122 IParaRouter02 _paraRouter 123 ) external onlyOwner { 124 t42 = _t42; 125 treasury = _treasury; 126 feeDistributor = _feeDistributor; 127 devaddr = _devaddr; 128 bonusEndBlock = _bonusEndBlock; 129 startBlock = _t42.startBlock(); 130 WETH = _WETH; 131 paraRouter = _paraRouter; 132 claimFeeRate = 500; 133 withdrawFeeRate = 130; 134 } 135 //the beginning of reentrancy bug: 136 function depositSingle(uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 137 depositSingleInternal(msg.sender, msg.sender, _pid, _token, _amount, paths, _minTokens); 138 } 139 //uint256 _minPoolTokens, 140 function depositSingleTo(address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) payable external{ 141 //Msg.sender is on the white list 142 IFeeDistributor(feeDistributor).setReferalByChef(_user, _whitelist[msg.sender]); 143 depositSingleInternal(msg.sender, _user, _pid, _token, _amount, paths, _minTokens); 144 } 145 struct DepositVars{ 146 uint oldBalance; 147 uint newBalance; 148 uint amountA; 149 uint amountB; 150 uint liquidity; 151 } 152 //During the reentrancy process, the UBT contract deposits 222 genuine LP tokens, which are credited to ParaProxy’s ledger. 153 //After the reentrancy is completed, 222 LP tokens are added to the ParaProxy contract address, 154 //which the ParaProxy contract treats as LPs added by the attack contract and credits to the ledger. 155 function depositSingleInternal(address payer, address _user, uint256 _pid, address _token, uint256 _amount, address[][2] memory paths, uint _minTokens) internal { 156 //Stack too deep, try removing local variables 157 DepositVars memory vars; 158 (_token, _amount) = _doTransferIn(payer, _token, _amount); 159 //swap by path 160 (address[2] memory tokens, uint[2] memory amounts) = depositSwapForTokens(_token, _amount, paths); 161 //Go approve 162 approveIfNeeded(tokens[0], address(paraRouter), amounts[0]); 163 approveIfNeeded(tokens[1], address(paraRouter), amounts[1]); 164 PoolInfo memory pool = poolInfo[_pid]; 165 //Non-VIP pool 166 //lp balance check 167 vars.oldBalance = pool.lpToken.balanceOf(address(this)); 168 (vars.amountA, vars.amountB, vars.liquidity) = paraRouter.addLiquidity(tokens[0], tokens[1], amounts[0], amounts[1], 1, 1, address(this), block.timestamp + 600); 169 vars.newBalance = pool.lpToken.balanceOf(address(this)); 170 //----------------- TODO 171 vars.liquidity = vars.newBalance.sub(vars.oldBalance); 172 addChange(_user, tokens[0], amounts[0].sub(vars.amountA)); 173 addChange(_user, tokens[1], amounts[1].sub(vars.amountB)); 174 //_deposit 175 _deposit(_pid, vars.liquidity, _user); 176 } 177 // Deposit LP tokens to MasterChef for T42 allocation. 178 function depositInternal(uint256 _pid, uint256 _amount, address _user, address payer) internal { 179 PoolInfo storage pool = poolInfo[_pid]; 180 pool.lpToken.safeTransferFrom( 181 address(payer), 182 address(this), 183 _amount 184 ); 185 if (address(pool.ticket) != address(0)) { 186 UserInfo storage user = userInfo[_pid][_user]; 187 uint256 new_amount = user.amount.add(_amount); 188 uint256 user_ticket_count = pool.ticket.tokensOfOwner(_user).length; 189 uint256 staked_ticket_count = ticket_staked_count(_user, address(pool.ticket)); 190 uint256 ticket_level = pool.ticket.level(); 191 (, uint overflow) = check_vip_limit(ticket_level, user_ticket_count + staked_ticket_count, new_amount); 192 deposit_all_tickets(pool.ticket); 193 } 194 _deposit(_pid, _amount, _user); 195 } 196 // Deposit LP tokens to MasterChef for para allocation. 197 function _deposit(uint256 _pid, uint256 _amount, address _user) internal { 198 PoolInfo storage pool = poolInfo[_pid]; 199 UserInfo storage user = userInfo[_pid][_user]; 200 //add total of pool before updatePool 201 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].add(_amount); 202 updatePool(_pid); 203 if (user.amount > 0) { 204 uint256 pending = 205 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 206 user.rewardDebt 207 ); 208 //TODO 209 _claim(pool.pooltype, pending); 210 } 211 user.amount = user.amount.add(_amount); 212 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 213 emit Deposit(_user, _pid, _amount); 214 } 215 function withdraw_tickets(uint256 _pid, uint256 tokenId) public { 216 //use memory for reduce gas 217 PoolInfo memory pool = poolInfo[_pid]; 218 UserInfo memory user = userInfo[_pid][msg.sender]; 219 //use storage because of updating value 220 uint256[] storage idlist = ticket_stakes[msg.sender][address(pool.ticket)]; 221 for (uint i; i< idlist.length; i++) { 222 if (idlist[i] == tokenId) { 223 (, uint overflow) = check_vip_limit(pool.ticket.level(), idlist.length - 1, user.amount); 224 pool.ticket.safeTransferFrom(address(this), msg.sender, tokenId); 225 idlist[i] = idlist[idlist.length - 1]; 226 idlist.pop(); 227 return; 228 } 229 } 230 } 231 // Withdraw LP tokens from MasterChef. 232 function withdraw(uint256 _pid, uint256 _amount) public { 233 _withdrawInternal(_pid, _amount, msg.sender); 234 emit Withdraw(msg.sender, _pid, _amount); 235 } 236 function _withdrawInternal(uint256 _pid, uint256 _amount, address _operator) internal{ 237 (address lpToken,uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, _operator); 238 IERC20(lpToken).safeTransfer(_operator, actual_amount); 239 } 240 function _withdrawWithoutTransfer(uint256 _pid, uint256 _amount, address _operator) internal returns (address lpToken, uint actual_amount){ 241 PoolInfo storage pool = poolInfo[_pid]; 242 UserInfo storage user = userInfo[_pid][_operator]; 243 updatePool(_pid); 244 uint256 pending = 245 user.amount.mul(pool.accT42PerShare).div(1e12).sub( 246 user.rewardDebt 247 ); 248 _claim(pool.pooltype, pending); 249 user.amount = user.amount.sub(_amount); 250 user.rewardDebt = user.amount.mul(pool.accT42PerShare).div(1e12); 251 //sub total of pool 252 poolsTotalDeposit[_pid] = poolsTotalDeposit[_pid].sub(_amount); 253 lpToken = address(pool.lpToken); 254 uint fee = _amount.mul(withdrawFeeRate).div(10000); 255 IERC20(lpToken).approve(feeDistributor, fee); 256 IFeeDistributor(feeDistributor).incomeWithdrawFee(_operator, lpToken, fee, _amount); 257 actual_amount = _amount.sub(fee); 258 } 259 function withdrawSingle(address tokenOut, uint256 _pid, uint256 _amount, address[][2] memory paths) external{ 260 //doWithraw Lp 261 (address lpToken, uint actual_amount) = _withdrawWithoutTransfer(_pid, _amount, msg.sender); 262 //remove liquidity 263 address[2] memory tokens; 264 uint[2] memory amounts; 265 tokens[0] = IParaPair(lpToken).token0(); 266 tokens[1] = IParaPair(lpToken).token1(); 267 //Go approve 268 approveIfNeeded(lpToken, address(paraRouter), actual_amount); 269 (amounts[0], amounts[1]) = paraRouter.removeLiquidity( 270 tokens[0], tokens[1], actual_amount, 0, 0, address(this), block.timestamp.add(600)); 271 //swap to tokenOut 272 for (uint i = 0; i < 2; i++){ 273 address[] memory path = paths[i]; 274 //Consider the same currency situation 275 if(path[0] == tokens[0]){ 276 swapTokensOut(amounts[0], tokenOut, path); 277 }else{ 278 swapTokensOut(amounts[1], tokenOut, path); 279 } 280 } 281 emit Withdraw(msg.sender, _pid, _amount); 282 } 283 function approveIfNeeded(address _token, address spender, uint _amount) private{ 284 if (IERC20(_token).allowance(address(this), spender) < _amount) { 285 IERC20(_token).approve(spender, _amount); 286 } 287 } | 109+ require(admin == msg.sender, "Ownable: caller is not the owner"); 141+ require(_whitelist[msg.sender] != address(0), "only white"); 155+ require(paths.length == 2,"deposit: PE"); 158+ require(_amount > 0, "deposit: zero"); 165+ require(address(pool.ticket) == address(0), "T:E"); 170+ require(vars.newBalance > vars.oldBalance, "B:E"); 171+ require(vars.liquidity >= _minTokens, "H:S"); 191+ require(overflow == 0, "Exceeding the ticket limit"); 223+ require(overflow == 0, "Please withdraw usdt in advance"); 229+ require(false, "You never staked this ticket before"); 242+ require(user.amount >= _amount, "withdraw: not good"); 259+ require(paths[0].length >= 2 && paths[1].length >= 2, "PE:2"); 259+ require(paths[0][paths[0].length - 1] == tokenOut,"invalid path_"); 259+ require(paths[1][paths[1].length - 1] == tokenOut,"invalid path_"); 273+ require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | 273+ | require(path[0] == tokens[0] || path[0] == tokens[1], "invalid path_0"); | |||||||||||||||||||||||
15 | 1 pragma solidity >=0.4.24 <0.6.0; 2 contract ExternalFunctionCall { 3 function foo(uint x) public returns (uint ret) { 4 ret = x + 2; 5 } 6 function testExternalFunctionCall(uint x) public { 7 uint y = this.foo(x); 8 } 9 } | 7+ assert (y == x + 2); | 7+ | assert (y == x + 2); | |||||||||||||||||||||||
16 | 1 pragma solidity >=0.4.24 <0.6.0; 2 contract B { 3 function funcB() public pure returns (uint) { 4 return 42; 5 } 6 constructor() public {} 7 } 8 contract A { 9 function funcA1() public pure returns (uint) { 10 return 11; 11 } 12 function funcA2(uint x) public pure returns (uint) { 13 return x+1; 14 } 15 function funcA3() public returns (B) { 16 B retVal= new B(); 17 return retVal; 18 } 19 constructor() public 20 { 21 } 22 } | 20+ assert(funcA2(funcA1())==12); 20+ assert(funcA3().funcB()==42); | 20+ | assert(funcA2(funcA1())==12); assert(funcA3().funcB()==42); | |||||||||||||||||||||||
17 | 1 pragma solidity >=0.4.24 <0.6.0; 2 // This test passes, but assertion on line 35 is only proved 3 // up to 4 transactions 4 // This result means that ctor A is only called once, for B, as A(x+1) 5 // Compare this test with ConstructorChaining2_fail.sol: no ctor args there, 6 // so the workaround in the compiler doesn't work, and the base ctor is called twice 7 // Example of the trace: 8 // D(x) is called, where x is 716 9 // B(x+3) called, where x is 716, B's arg is 719 10 // A(x+1) called, where x is 720. A's arg is 720 11 // ctor A {a = x} , where a is 720 12 // ctor B {b = x+1 } , where x is 719, b is 720 13 // C(x+4) is called, where x is 716, C's arg is 720 14 // ctor C { c = x + 2}, where x is 720, c is 722 15 contract A { 16 uint a; 17 constructor (uint x) public { 18 a = x; 19 } 20 } 21 contract B is A { 22 uint b; 23 constructor (uint x) A(x+1) public { 24 b = x + 1; 25 } 26 } 27 contract C is A { 28 uint c; 29 //constructor (uint x) A(x+2) public { // no A with ANY args here, otherwise, solc error: 30 // "Base constr args given twice" 31 constructor (uint x) public { 32 c = x + 2; 33 } 34 } 35 contract D is B, C { 36 constructor (uint x) B(x+3) C(x+4) public 37 { 38 } 39 } | 24+ assert(a == x + 1); 32+ assert(a == x); 37+ assert (a == x + 4); 37+ assert (b == x + 4); 37+ assert (c == x + 6); | 24+ | assert(a == x + 1); | |||||||||||||||||||||||
18 | 1 pragma solidity >=0.4.24 <0.6.0; 2 // This test passes, but assertion on line 35 is only proved 3 // up to 4 transactions 4 // This result means that ctor A is only called once, for B, as A(x+1) 5 // Compare this test with ConstructorChaining2_fail.sol: no ctor args there, 6 // so the workaround in the compiler doesn't work, and the base ctor is called twice 7 // Example of the trace: 8 // D(x) is called, where x is 716 9 // B(x+3) called, where x is 716, B's arg is 719 10 // A(x+1) called, where x is 720. A's arg is 720 11 // ctor A {a = x} , where a is 720 12 // ctor B {b = x+1 } , where x is 719, b is 720 13 // C(x+4) is called, where x is 716, C's arg is 720 14 // ctor C { c = x + 2}, where x is 720, c is 722 15 contract A { 16 uint a; 17 constructor (uint x) public { 18 a = x; 19 } 20 } 21 contract B is A { 22 uint b; 23 constructor (uint x) A(x+1) public { 24 b = x + 1; 25 } 26 } 27 contract C is A { 28 uint c; 29 //constructor (uint x) A(x+2) public { // no A with ANY args here, otherwise, solc error: 30 // "Base constr args given twice" 31 constructor (uint x) public { 32 c = x + 2; 33 } 34 } 35 contract D is B, C { 36 constructor (uint x) B(x+3) C(x+4) public 37 { 38 } 39 } | 24+ assert(a == x + 1); 32+ assert(a == x); 37+ assert (a == x + 4); 37+ assert (b == x + 4); 37+ assert (c == x + 6); | 32+ | assert(a == x); | |||||||||||||||||||||||
19 | 1 pragma solidity >=0.4.24 <0.6.0; 2 // This test passes, but assertion on line 35 is only proved 3 // up to 4 transactions 4 // This result means that ctor A is only called once, for B, as A(x+1) 5 // Compare this test with ConstructorChaining2_fail.sol: no ctor args there, 6 // so the workaround in the compiler doesn't work, and the base ctor is called twice 7 // Example of the trace: 8 // D(x) is called, where x is 716 9 // B(x+3) called, where x is 716, B's arg is 719 10 // A(x+1) called, where x is 720. A's arg is 720 11 // ctor A {a = x} , where a is 720 12 // ctor B {b = x+1 } , where x is 719, b is 720 13 // C(x+4) is called, where x is 716, C's arg is 720 14 // ctor C { c = x + 2}, where x is 720, c is 722 15 contract A { 16 uint a; 17 constructor (uint x) public { 18 a = x; 19 } 20 } 21 contract B is A { 22 uint b; 23 constructor (uint x) A(x+1) public { 24 b = x + 1; 25 } 26 } 27 contract C is A { 28 uint c; 29 //constructor (uint x) A(x+2) public { // no A with ANY args here, otherwise, solc error: 30 // "Base constr args given twice" 31 constructor (uint x) public { 32 c = x + 2; 33 } 34 } 35 contract D is B, C { 36 constructor (uint x) B(x+3) C(x+4) public 37 { 38 } 39 } | 24+ assert(a == x + 1); 32+ assert(a == x); 37+ assert (a == x + 4); 37+ assert (b == x + 4); 37+ assert (c == x + 6); | 37+ | assert (a == x + 4); assert (b == x + 4); assert (c == x + 6); | |||||||||||||||||||||||
20 | 1 pragma solidity >=0.4.24 <0.6.0; 2 contract B { 3 function funcB() public pure returns (uint) { 4 return 42; 5 } 6 constructor() public {} 7 } 8 contract A { 9 function funcA1() public pure returns (uint) { 10 return 11; 11 } 12 function funcA2(uint x) public pure returns (uint) { 13 return x+1; 14 } 15 function funcA3() public returns (B) { 16 B retVal= new B(); 17 return retVal; 18 } 19 constructor() public 20 { 21 } 22 } | 20+ assert(funcA2(funcA1())==12); 20+ assert(funcA3().funcB()==42); | 20+ | assert(funcA2(funcA1())==12); assert(funcA3().funcB()==42); | |||||||||||||||||||||||
21 | 1 pragma solidity >=0.4.24 <0.6.0; 2 // This test passes, but assertion on line 35 is only proved 3 // up to 4 transactions 4 // This result means that ctor A is only called once, for B, as A(x+1) 5 // Compare this test with ConstructorChaining2_fail.sol: no ctor args there, 6 // so the workaround in the compiler doesn't work, and the base ctor is called twice 7 // Example of the trace: 8 // D(x) is called, where x is 716 9 // B(x+3) called, where x is 716, B's arg is 719 10 // A(x+1) called, where x is 720. A's arg is 720 11 // ctor A {a = x} , where a is 720 12 // ctor B {b = x+1 } , where x is 719, b is 720 13 // C(x+4) is called, where x is 716, C's arg is 720 14 // ctor C { c = x + 2}, where x is 720, c is 722 15 contract A { 16 uint a; 17 constructor (uint x) public { 18 a = x; 19 } 20 } 21 contract B is A { 22 uint b; 23 constructor (uint x) A(x+1) public { 24 b = x + 1; 25 } 26 } 27 contract C is A { 28 uint c; 29 //constructor (uint x) A(x+2) public { // no A with ANY args here, otherwise, solc error: 30 // "Base constr args given twice" 31 constructor (uint x) public { 32 c = x + 2; 33 // passes, but proved to only 4 transactions 34 } 35 } 36 contract D is B, C { 37 constructor (uint x) B(x+3) C(x+4) public 38 { 39 ; 40 } 41 } | 24+ assert(a == x + 1); 32+ assert(a == x); 38+ assert (a == x + 4); 38+ assert (b == x + 4); 38+ assert (c == x + 6); | 24+ | assert(a == x + 1); | |||||||||||||||||||||||
22 | 1 pragma solidity >=0.4.24 <0.6.0; 2 // This test passes, but assertion on line 35 is only proved 3 // up to 4 transactions 4 // This result means that ctor A is only called once, for B, as A(x+1) 5 // Compare this test with ConstructorChaining2_fail.sol: no ctor args there, 6 // so the workaround in the compiler doesn't work, and the base ctor is called twice 7 // Example of the trace: 8 // D(x) is called, where x is 716 9 // B(x+3) called, where x is 716, B's arg is 719 10 // A(x+1) called, where x is 720. A's arg is 720 11 // ctor A {a = x} , where a is 720 12 // ctor B {b = x+1 } , where x is 719, b is 720 13 // C(x+4) is called, where x is 716, C's arg is 720 14 // ctor C { c = x + 2}, where x is 720, c is 722 15 contract A { 16 uint a; 17 constructor (uint x) public { 18 a = x; 19 } 20 } 21 contract B is A { 22 uint b; 23 constructor (uint x) A(x+1) public { 24 b = x + 1; 25 } 26 } 27 contract C is A { 28 uint c; 29 //constructor (uint x) A(x+2) public { // no A with ANY args here, otherwise, solc error: 30 // "Base constr args given twice" 31 constructor (uint x) public { 32 c = x + 2; 33 // passes, but proved to only 4 transactions 34 } 35 } 36 contract D is B, C { 37 constructor (uint x) B(x+3) C(x+4) public 38 { 39 ; 40 } 41 } | 24+ assert(a == x + 1); 32+ assert(a == x); 38+ assert (a == x + 4); 38+ assert (b == x + 4); 38+ assert (c == x + 6); | 32+ | assert(a == x); | |||||||||||||||||||||||
23 | 1 pragma solidity >=0.4.24 <0.6.0; 2 // This test passes, but assertion on line 35 is only proved 3 // up to 4 transactions 4 // This result means that ctor A is only called once, for B, as A(x+1) 5 // Compare this test with ConstructorChaining2_fail.sol: no ctor args there, 6 // so the workaround in the compiler doesn't work, and the base ctor is called twice 7 // Example of the trace: 8 // D(x) is called, where x is 716 9 // B(x+3) called, where x is 716, B's arg is 719 10 // A(x+1) called, where x is 720. A's arg is 720 11 // ctor A {a = x} , where a is 720 12 // ctor B {b = x+1 } , where x is 719, b is 720 13 // C(x+4) is called, where x is 716, C's arg is 720 14 // ctor C { c = x + 2}, where x is 720, c is 722 15 contract A { 16 uint a; 17 constructor (uint x) public { 18 a = x; 19 } 20 } 21 contract B is A { 22 uint b; 23 constructor (uint x) A(x+1) public { 24 b = x + 1; 25 } 26 } 27 contract C is A { 28 uint c; 29 //constructor (uint x) A(x+2) public { // no A with ANY args here, otherwise, solc error: 30 // "Base constr args given twice" 31 constructor (uint x) public { 32 c = x + 2; 33 // passes, but proved to only 4 transactions 34 } 35 } 36 contract D is B, C { 37 constructor (uint x) B(x+3) C(x+4) public 38 { 39 ; 40 } 41 } | 24+ assert(a == x + 1); 32+ assert(a == x); 38+ assert (a == x + 4); 38+ assert (b == x + 4); 38+ assert (c == x + 6); | 38+ | assert (a == x + 4); assert (b == x + 4); assert (c == x + 6); | |||||||||||||||||||||||
24 | 1 pragma solidity >=0.4.24<0.6.0; 2 import "./Libraries/VeriSolContracts.sol"; 3 contract LoopFor { 4 int x; 5 int y; 6 function ContractInvariant () private view { 7 } 8 // test Loop invariant with for loop 9 constructor(int n) public { 10 require (n >= 0); 11 x = n; 12 y = x; 13 } 14 function Foo() public { 15 if ( x > 0 ) 16 { 17 x--; 18 y--; 19 } 20 } 21 } | 6+ assert(x == y); 6+ assert(y >= 0); 19+ assert (y >= 0); | 6+ | assert(x == y); assert(y >= 0); | |||||||||||||||||||||||
25 | 1 pragma solidity >=0.4.24<0.6.0; 2 import "./Libraries/VeriSolContracts.sol"; 3 contract LoopFor { 4 int x; 5 int y; 6 function ContractInvariant () private view { 7 } 8 // test Loop invariant with for loop 9 constructor(int n) public { 10 require (n >= 0); 11 x = n; 12 y = x; 13 } 14 function Foo() public { 15 if ( x > 0 ) 16 { 17 x--; 18 y--; 19 } 20 } 21 } | 6+ assert(x == y); 6+ assert(y >= 0); 19+ assert (y >= 0); | 19+ | assert (y >= 0); | |||||||||||||||||||||||
26 | pragma solidity >=0.4.24 <0.6.0; //simple library with no internal state library Lib { function add(uint _a, uint _b) public view returns (uint r) { address x = address(this); r = _a + _b; } } contract C { // using Lib for uint; function foo() public { uint x = 1; uint y = 2; uint z = Lib.add(x, y); } } | 5+ assert(x == msg.sender); 14+ assert (z == 3); | 5+ | assert(x == msg.sender); | |||||||||||||||||||||||
27 | pragma solidity >=0.4.24 <0.6.0; //simple library with no internal state library Lib { function add(uint _a, uint _b) public view returns (uint r) { address x = address(this); r = _a + _b; } } contract C { // using Lib for uint; function foo() public { uint x = 1; uint y = 2; uint z = Lib.add(x, y); } } | 5+ assert(x == msg.sender); 14+ assert (z == 3); | 14+ | assert (z == 3); | |||||||||||||||||||||||
28 | 1 pragma solidity ^0.4.24; 2 import "./../../Libraries/VeriSolContracts.sol"; 3 //import "./VeriSolContracts.sol"; 4 //import "github.com/microsoft/verisol/blob/master/Libraries/VeriSolContracts.sol"; 5 contract LoopFor { 6 // test Loop invariant with for loop 7 constructor(uint n) public { 8 require (n >= 0); 9 uint y = 0; 10 for (uint x = n; x != 0; x --) { 11 y++; 12 } 13 } 14 // test Loop invariant with while loop 15 function Foo(uint n) public { 16 require (n >= 0); 17 uint y = 0; 18 uint x = n; 19 while (x != 0) { 20 y++; 21 x--; 22 } 23 } 24 // test Loop invariant with do-while loop 25 function Bar(uint n) public { 26 require (n > 0); 27 uint y = 0; 28 uint x = n; 29 do { 30 y++; 31 x--; 32 } while (x != 0); 33 } 34 } | 10+ assert(x + y == n); 12+ assert (y == n); 19+ assert(x + y == n); 22+ assert (y == n); 29+ assert(x + y == n); 32+ assert (y == n); | 10+ | assert(x + y == n); | |||||||||||||||||||||||
29 | 1 pragma solidity ^0.4.24; 2 import "./../../Libraries/VeriSolContracts.sol"; 3 //import "./VeriSolContracts.sol"; 4 //import "github.com/microsoft/verisol/blob/master/Libraries/VeriSolContracts.sol"; 5 contract LoopFor { 6 // test Loop invariant with for loop 7 constructor(uint n) public { 8 require (n >= 0); 9 uint y = 0; 10 for (uint x = n; x != 0; x --) { 11 y++; 12 } 13 } 14 // test Loop invariant with while loop 15 function Foo(uint n) public { 16 require (n >= 0); 17 uint y = 0; 18 uint x = n; 19 while (x != 0) { 20 y++; 21 x--; 22 } 23 } 24 // test Loop invariant with do-while loop 25 function Bar(uint n) public { 26 require (n > 0); 27 uint y = 0; 28 uint x = n; 29 do { 30 y++; 31 x--; 32 } while (x != 0); 33 } 34 } | 10+ assert(x + y == n); 12+ assert (y == n); 19+ assert(x + y == n); 22+ assert (y == n); 29+ assert(x + y == n); 32+ assert (y == n); | 12+ | assert (y == n); | |||||||||||||||||||||||
30 | 1 pragma solidity ^0.4.24; 2 import "./../../Libraries/VeriSolContracts.sol"; 3 //import "./VeriSolContracts.sol"; 4 //import "github.com/microsoft/verisol/blob/master/Libraries/VeriSolContracts.sol"; 5 contract LoopFor { 6 // test Loop invariant with for loop 7 constructor(uint n) public { 8 require (n >= 0); 9 uint y = 0; 10 for (uint x = n; x != 0; x --) { 11 y++; 12 } 13 } 14 // test Loop invariant with while loop 15 function Foo(uint n) public { 16 require (n >= 0); 17 uint y = 0; 18 uint x = n; 19 while (x != 0) { 20 y++; 21 x--; 22 } 23 } 24 // test Loop invariant with do-while loop 25 function Bar(uint n) public { 26 require (n > 0); 27 uint y = 0; 28 uint x = n; 29 do { 30 y++; 31 x--; 32 } while (x != 0); 33 } 34 } | 10+ assert(x + y == n); 12+ assert (y == n); 19+ assert(x + y == n); 22+ assert (y == n); 29+ assert(x + y == n); 32+ assert (y == n); | 19+ | assert(x + y == n); | |||||||||||||||||||||||
31 | 1 pragma solidity ^0.4.24; 2 import "./../../Libraries/VeriSolContracts.sol"; 3 //import "./VeriSolContracts.sol"; 4 //import "github.com/microsoft/verisol/blob/master/Libraries/VeriSolContracts.sol"; 5 contract LoopFor { 6 // test Loop invariant with for loop 7 constructor(uint n) public { 8 require (n >= 0); 9 uint y = 0; 10 for (uint x = n; x != 0; x --) { 11 y++; 12 } 13 } 14 // test Loop invariant with while loop 15 function Foo(uint n) public { 16 require (n >= 0); 17 uint y = 0; 18 uint x = n; 19 while (x != 0) { 20 y++; 21 x--; 22 } 23 } 24 // test Loop invariant with do-while loop 25 function Bar(uint n) public { 26 require (n > 0); 27 uint y = 0; 28 uint x = n; 29 do { 30 y++; 31 x--; 32 } while (x != 0); 33 } 34 } | 10+ assert(x + y == n); 12+ assert (y == n); 19+ assert(x + y == n); 22+ assert (y == n); 29+ assert(x + y == n); 32+ assert (y == n); | 22+ | assert (y == n); | |||||||||||||||||||||||
32 | 1 pragma solidity ^0.4.24; 2 import "./../../Libraries/VeriSolContracts.sol"; 3 //import "./VeriSolContracts.sol"; 4 //import "github.com/microsoft/verisol/blob/master/Libraries/VeriSolContracts.sol"; 5 contract LoopFor { 6 // test Loop invariant with for loop 7 constructor(uint n) public { 8 require (n >= 0); 9 uint y = 0; 10 for (uint x = n; x != 0; x --) { 11 y++; 12 } 13 } 14 // test Loop invariant with while loop 15 function Foo(uint n) public { 16 require (n >= 0); 17 uint y = 0; 18 uint x = n; 19 while (x != 0) { 20 y++; 21 x--; 22 } 23 } 24 // test Loop invariant with do-while loop 25 function Bar(uint n) public { 26 require (n > 0); 27 uint y = 0; 28 uint x = n; 29 do { 30 y++; 31 x--; 32 } while (x != 0); 33 } 34 } | 10+ assert(x + y == n); 12+ assert (y == n); 19+ assert(x + y == n); 22+ assert (y == n); 29+ assert(x + y == n); 32+ assert (y == n); | 29+ | assert(x + y == n); | |||||||||||||||||||||||
33 | 1 pragma solidity ^0.4.24; 2 import "./../../Libraries/VeriSolContracts.sol"; 3 //import "./VeriSolContracts.sol"; 4 //import "github.com/microsoft/verisol/blob/master/Libraries/VeriSolContracts.sol"; 5 contract LoopFor { 6 // test Loop invariant with for loop 7 constructor(uint n) public { 8 require (n >= 0); 9 uint y = 0; 10 for (uint x = n; x != 0; x --) { 11 y++; 12 } 13 } 14 // test Loop invariant with while loop 15 function Foo(uint n) public { 16 require (n >= 0); 17 uint y = 0; 18 uint x = n; 19 while (x != 0) { 20 y++; 21 x--; 22 } 23 } 24 // test Loop invariant with do-while loop 25 function Bar(uint n) public { 26 require (n > 0); 27 uint y = 0; 28 uint x = n; 29 do { 30 y++; 31 x--; 32 } while (x != 0); 33 } 34 } | 10+ assert(x + y == n); 12+ assert (y == n); 19+ assert(x + y == n); 22+ assert (y == n); 29+ assert(x + y == n); 32+ assert (y == n); | 32+ | assert (y == n); | |||||||||||||||||||||||
34 | 1 pragma solidity ^0.5.0; 2 import "./IERC20.sol"; 3 import "./SafeMath.sol"; 4 import "./Libraries/VeriSolContracts.sol"; //change 5 /** 6 * A highly simplified Token to express basic specifications 7 * 8 * - totalSupply() equals the Sum({balanceOf(a) | a is an address }) 9 * 10 */ 11 contract ERC20 is IERC20 { 12 mapping (address => uint256) private _balances; 13 uint256 private _totalSupply; 14 /** 15 * A dummy constructor 16 */ 17 constructor (uint256 totalSupply) public { 18 _totalSupply = totalSupply; 19 _balances[msg.sender] = totalSupply; 20 } 21 /** 22 * @dev See {IERC20-totalSupply}. 23 */ 24 function totalSupply() public view returns (uint256) { 25 return _totalSupply; 26 } 27 /** 28 * @dev See {IERC20-balanceOf}. 29 */ 30 function balanceOf(address account) public view returns (uint256) { 31 return _balances[account]; 32 } 33 /** 34 * @dev See {IERC20-transfer}. 35 * 36 * Requirements: 37 * 38 * - `recipient` cannot be the zero address. 39 * - the caller must have a balance of at least `amount`. 40 */ 41 function transfer(address recipient, uint256 amount) public returns (bool) { 42 uint oldBalanceSender = _balances[msg.sender]; 43 _transfer(msg.sender, recipient, amount); 44 //assert (/* msg.sender == recipient || */ _balances[msg.sender] == oldBalanceSender - amount); 45 // the following assertion will fail due to overflow when not using safemath 46 // to detect it, run with /modularArith flag 47 // to prove it, run ERC20 with /modularArith flag 48 return true; 49 } 50 /** 51 * @dev Moves tokens `amount` from `sender` to `recipient`. 52 * 53 * This is internal function is equivalent to {transfer}, and can be used to 54 * e.g. implement automatic token fees, slashing mechanisms, etc. 55 * 56 * Emits a {Transfer} event. 57 * 58 * Requirements: 59 * 60 * - `sender` cannot be the zero address. 61 * - `recipient` cannot be the zero address. 62 * - `sender` must have a balance of at least `amount`. 63 */ 64 function _transfer(address sender, address recipient, uint256 amount) internal { 65 require(sender != address(0), "ERC20: transfer from the zero address"); 66 require(recipient != address(0), "ERC20: transfer to the zero address"); 67 _balances[sender] = SafeMath.sub(_balances[sender], amount); 68 _balances[recipient] = _balances[recipient] + amount; // nosafemath //_balances[recipient] = _balances[recipient].add(amount); 69 } 70 } | 17+ require(msg.sender != address(0)); 47+ assert (msg.sender == recipient || _balances[recipient] >= VeriSol.Old(_balances[recipient])); 66+ require(_balances[sender] >= amount); | 17+ | require(msg.sender != address(0)); | |||||||||||||||||||||||
35 | 1 pragma solidity ^0.5.0; 2 import "./IERC20.sol"; 3 import "./SafeMath.sol"; 4 import "./Libraries/VeriSolContracts.sol"; //change 5 /** 6 * A highly simplified Token to express basic specifications 7 * 8 * - totalSupply() equals the Sum({balanceOf(a) | a is an address }) 9 * 10 */ 11 contract ERC20 is IERC20 { 12 mapping (address => uint256) private _balances; 13 uint256 private _totalSupply; 14 /** 15 * A dummy constructor 16 */ 17 constructor (uint256 totalSupply) public { 18 _totalSupply = totalSupply; 19 _balances[msg.sender] = totalSupply; 20 } 21 /** 22 * @dev See {IERC20-totalSupply}. 23 */ 24 function totalSupply() public view returns (uint256) { 25 return _totalSupply; 26 } 27 /** 28 * @dev See {IERC20-balanceOf}. 29 */ 30 function balanceOf(address account) public view returns (uint256) { 31 return _balances[account]; 32 } 33 /** 34 * @dev See {IERC20-transfer}. 35 * 36 * Requirements: 37 * 38 * - `recipient` cannot be the zero address. 39 * - the caller must have a balance of at least `amount`. 40 */ 41 function transfer(address recipient, uint256 amount) public returns (bool) { 42 uint oldBalanceSender = _balances[msg.sender]; 43 _transfer(msg.sender, recipient, amount); 44 //assert (/* msg.sender == recipient || */ _balances[msg.sender] == oldBalanceSender - amount); 45 // the following assertion will fail due to overflow when not using safemath 46 // to detect it, run with /modularArith flag 47 // to prove it, run ERC20 with /modularArith flag 48 return true; 49 } 50 /** 51 * @dev Moves tokens `amount` from `sender` to `recipient`. 52 * 53 * This is internal function is equivalent to {transfer}, and can be used to 54 * e.g. implement automatic token fees, slashing mechanisms, etc. 55 * 56 * Emits a {Transfer} event. 57 * 58 * Requirements: 59 * 60 * - `sender` cannot be the zero address. 61 * - `recipient` cannot be the zero address. 62 * - `sender` must have a balance of at least `amount`. 63 */ 64 function _transfer(address sender, address recipient, uint256 amount) internal { 65 require(sender != address(0), "ERC20: transfer from the zero address"); 66 require(recipient != address(0), "ERC20: transfer to the zero address"); 67 _balances[sender] = SafeMath.sub(_balances[sender], amount); 68 _balances[recipient] = _balances[recipient] + amount; // nosafemath //_balances[recipient] = _balances[recipient].add(amount); 69 } 70 } | 17+ require(msg.sender != address(0)); 47+ assert (msg.sender == recipient || _balances[recipient] >= VeriSol.Old(_balances[recipient])); 66+ require(_balances[sender] >= amount); | 47+ | assert (msg.sender == recipient || _balances[recipient] >= VeriSol.Old(_balances[recipient])); | |||||||||||||||||||||||
36 | 1 pragma solidity ^0.5.0; 2 import "./IERC20.sol"; 3 import "./SafeMath.sol"; 4 import "./Libraries/VeriSolContracts.sol"; //change 5 /** 6 * A highly simplified Token to express basic specifications 7 * 8 * - totalSupply() equals the Sum({balanceOf(a) | a is an address }) 9 * 10 */ 11 contract ERC20 is IERC20 { 12 mapping (address => uint256) private _balances; 13 uint256 private _totalSupply; 14 /** 15 * A dummy constructor 16 */ 17 constructor (uint256 totalSupply) public { 18 _totalSupply = totalSupply; 19 _balances[msg.sender] = totalSupply; 20 } 21 /** 22 * @dev See {IERC20-totalSupply}. 23 */ 24 function totalSupply() public view returns (uint256) { 25 return _totalSupply; 26 } 27 /** 28 * @dev See {IERC20-balanceOf}. 29 */ 30 function balanceOf(address account) public view returns (uint256) { 31 return _balances[account]; 32 } 33 /** 34 * @dev See {IERC20-transfer}. 35 * 36 * Requirements: 37 * 38 * - `recipient` cannot be the zero address. 39 * - the caller must have a balance of at least `amount`. 40 */ 41 function transfer(address recipient, uint256 amount) public returns (bool) { 42 uint oldBalanceSender = _balances[msg.sender]; 43 _transfer(msg.sender, recipient, amount); 44 //assert (/* msg.sender == recipient || */ _balances[msg.sender] == oldBalanceSender - amount); 45 // the following assertion will fail due to overflow when not using safemath 46 // to detect it, run with /modularArith flag 47 // to prove it, run ERC20 with /modularArith flag 48 return true; 49 } 50 /** 51 * @dev Moves tokens `amount` from `sender` to `recipient`. 52 * 53 * This is internal function is equivalent to {transfer}, and can be used to 54 * e.g. implement automatic token fees, slashing mechanisms, etc. 55 * 56 * Emits a {Transfer} event. 57 * 58 * Requirements: 59 * 60 * - `sender` cannot be the zero address. 61 * - `recipient` cannot be the zero address. 62 * - `sender` must have a balance of at least `amount`. 63 */ 64 function _transfer(address sender, address recipient, uint256 amount) internal { 65 require(sender != address(0), "ERC20: transfer from the zero address"); 66 require(recipient != address(0), "ERC20: transfer to the zero address"); 67 _balances[sender] = SafeMath.sub(_balances[sender], amount); 68 _balances[recipient] = _balances[recipient] + amount; // nosafemath //_balances[recipient] = _balances[recipient].add(amount); 69 } 70 } | 17+ require(msg.sender != address(0)); 47+ assert (msg.sender == recipient || _balances[recipient] >= VeriSol.Old(_balances[recipient])); 66+ require(_balances[sender] >= amount); | 66+ | require(_balances[sender] >= amount); | |||||||||||||||||||||||
37 | 1 //SPDX-License-Identifier: MIT 2 pragma solidity 0.7.5; 3 contract contrived{ 4 function withdraw(uint256 amount) override public nonReentrant updateReward(msg.sender) { 5 _totalSupply = _totalSupply - amount; 6 _balances[msg.sender] = _balances[msg.sender].sub(amount); 7 stakingToken.safeTransfer(msg.sender, amount); 8 emit Withdrawn(msg.sender, amount); 9 } 10 } | 4+ require(amount > 0, "Cannot withdraw 0"); | 4+ | require(amount > 0, "Cannot withdraw 0"); | |||||||||||||||||||||||
38 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 11+ | assert(a == 0 || c / a == b); | |||||||||||||||||||||||
39 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 20+ | assert(b <= a); | |||||||||||||||||||||||
40 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 24+ | assert(c >= a); | |||||||||||||||||||||||
41 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 51+ | require(_to != address(0)); require(_value > 0 && _value <= balances[msg.sender]); | |||||||||||||||||||||||
42 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 145+ | require(msg.sender == owner); | |||||||||||||||||||||||
43 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 152+ | require(newOwner != address(0)); | |||||||||||||||||||||||
44 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 168+ | require(!paused); | |||||||||||||||||||||||
45 | 1 /** 2 *Submitted for verification at Etherscan.io on 2018-02-09 3 */ 4 pragma solidity ^0.4.16; 5 /** 6 * @title SafeMath 7 * @dev Math operations with safety checks that throw on error 8 */ 9 library SafeMath { 10 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 11 uint256 c = a * b; 12 return c; 13 } 14 function div(uint256 a, uint256 b) internal constant returns (uint256) { 15 // assert(b > 0); // Solidity automatically throws when dividing by 0 16 uint256 c = a / b; 17 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 18 return c; 19 } 20 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 21 return a - b; 22 } 23 function add(uint256 a, uint256 b) internal constant returns (uint256) { 24 uint256 c = a + b; 25 return c; 26 } 27 } 28 /** 29 * @title ERC20Basic 30 * @dev Simpler version of ERC20 interface 31 * @dev see https://github.com/ethereum/EIPs/issues/179 32 */ 33 contract ERC20Basic { 34 uint256 public totalSupply; 35 function balanceOf(address who) public constant returns (uint256); 36 function transfer(address to, uint256 value) public returns (bool); 37 event Transfer(address indexed from, address indexed to, uint256 value); 38 } 39 /** 40 * @title Basic token 41 * @dev Basic version of StandardToken, with no allowances. 42 */ 43 contract BasicToken is ERC20Basic { 44 using SafeMath for uint256; 45 mapping(address => uint256) balances; 46 /** 47 * @dev transfer token for a specified address 48 * @param _to The address to transfer to. 49 * @param _value The amount to be transferred. 50 */ 51 function transfer(address _to, uint256 _value) public returns (bool) { 52 // SafeMath.sub will throw if there is not enough balance. 53 balances[msg.sender] = balances[msg.sender].sub(_value); 54 balances[_to] = balances[_to].add(_value); 55 Transfer(msg.sender, _to, _value); 56 return true; 57 } 58 /** 59 * @dev Gets the balance of the specified address. 60 * @param _owner The address to query the the balance of. 61 * @return An uint256 representing the amount owned by the passed address. 62 */ 63 function balanceOf(address _owner) public constant returns (uint256 balance) { 64 return balances[_owner]; 65 } 66 } 67 /** 68 * @title ERC20 interface 69 * @dev see https://github.com/ethereum/EIPs/issues/20 70 */ 71 contract ERC20 is ERC20Basic { 72 function allowance(address owner, address spender) public constant returns (uint256); 73 function transferFrom(address from, address to, uint256 value) public returns (bool); 74 function approve(address spender, uint256 value) public returns (bool); 75 event Approval(address indexed owner, address indexed spender, uint256 value); 76 } 77 /** 78 * @title Standard ERC20 token 79 * 80 * @dev Implementation of the basic standard token. 81 * @dev https://github.com/ethereum/EIPs/issues/20 82 * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol 83 */ 84 contract StandardToken is ERC20, BasicToken { 85 mapping (address => mapping (address => uint256)) internal allowed; 86 /** 87 * @dev Transfer tokens from one address to another 88 * @param _from address The address which you want to send tokens from 89 * @param _to address The address which you want to transfer to 90 * @param _value uint256 the amount of tokens to be transferred 91 */ 92 function transferFrom(address _from, address _to, uint256 _value) public returns (bool) { 93 require(_to != address(0)); 94 require(_value > 0 && _value <= balances[_from]); 95 require(_value <= allowed[_from][msg.sender]); 96 balances[_from] = balances[_from].sub(_value); 97 balances[_to] = balances[_to].add(_value); 98 allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); 99 Transfer(_from, _to, _value); 100 return true; 101 } 102 /** 103 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender. 104 * 105 * Beware that changing an allowance with this method brings the risk that someone may use both the old 106 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this 107 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards: 108 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 109 * @param _spender The address which will spend the funds. 110 * @param _value The amount of tokens to be spent. 111 */ 112 function approve(address _spender, uint256 _value) public returns (bool) { 113 allowed[msg.sender][_spender] = _value; 114 Approval(msg.sender, _spender, _value); 115 return true; 116 } 117 /** 118 * @dev Function to check the amount of tokens that an owner allowed to a spender. 119 * @param _owner address The address which owns the funds. 120 * @param _spender address The address which will spend the funds. 121 * @return A uint256 specifying the amount of tokens still available for the spender. 122 */ 123 function allowance(address _owner, address _spender) public constant returns (uint256 remaining) { 124 return allowed[_owner][_spender]; 125 } 126 } 127 /** 128 * @title Ownable 129 * @dev The Ownable contract has an owner address, and provides basic authorization control 130 * functions, this simplifies the implementation of "user permissions". 131 */ 132 contract Ownable { 133 address public owner; 134 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 135 /** 136 * @dev The Ownable constructor sets the original `owner` of the contract to the sender 137 * account. 138 */ 139 function Ownable() { 140 owner = msg.sender; 141 } 142 /** 143 * @dev Throws if called by any account other than the owner. 144 */ 145 modifier onlyOwner() { 146 _; 147 } 148 /** 149 * @dev Allows the current owner to transfer control of the contract to a newOwner. 150 * @param newOwner The address to transfer ownership to. 151 */ 152 function transferOwnership(address newOwner) onlyOwner public { 153 OwnershipTransferred(owner, newOwner); 154 owner = newOwner; 155 } 156 } 157 /** 158 * @title Pausable 159 * @dev Base contract which allows children to implement an emergency stop mechanism. 160 */ 161 contract Pausable is Ownable { 162 event Pause(); 163 event Unpause(); 164 bool public paused = false; 165 /** 166 * @dev Modifier to make a function callable only when the contract is not paused. 167 */ 168 modifier whenNotPaused() { 169 _; 170 } 171 /** 172 * @dev Modifier to make a function callable only when the contract is paused. 173 */ 174 modifier whenPaused() { 175 _; 176 } 177 /** 178 * @dev called by the owner to pause, triggers stopped state 179 */ 180 function pause() onlyOwner whenNotPaused public { 181 paused = true; 182 Pause(); 183 } 184 /** 185 * @dev called by the owner to unpause, returns to normal state 186 */ 187 function unpause() onlyOwner whenPaused public { 188 paused = false; 189 Unpause(); 190 } 191 } 192 /** 193 * @title Pausable token 194 * 195 * @dev StandardToken modified with pausable transfers. 196 **/ 197 contract PausableToken is StandardToken, Pausable { 198 function transfer(address _to, uint256 _value) public whenNotPaused returns (bool) { 199 return super.transfer(_to, _value); 200 } 201 function transferFrom(address _from, address _to, uint256 _value) public whenNotPaused returns (bool) { 202 return super.transferFrom(_from, _to, _value); 203 } 204 function approve(address _spender, uint256 _value) public whenNotPaused returns (bool) { 205 return super.approve(_spender, _value); 206 } 207 function batchTransfer(address[] _receivers, uint256 _value) public whenNotPaused returns (bool) { 208 uint cnt = _receivers.length; 209 uint256 amount = uint256(cnt) * _value; 210 require(cnt > 0 && cnt <= 20); 211 require(_value > 0 && balances[msg.sender] >= amount); 212 balances[msg.sender] = balances[msg.sender].sub(amount); 213 for (uint i = 0; i < cnt; i++) { 214 balances[_receivers[i]] = balances[_receivers[i]].add(_value); 215 Transfer(msg.sender, _receivers[i], _value); 216 } 217 return true; 218 } 219 } 220 /** 221 * @title Bec Token 222 * 223 * @dev Implementation of Bec Token based on the basic standard token. 224 */ 225 contract BecToken is PausableToken { 226 /** 227 * Public variables of the token 228 * The following variables are OPTIONAL vanities. One does not have to include them. 229 * They allow one to customise the token contract & in no way influences the core functionality. 230 * Some wallets/interfaces might not even bother to look at this information. 231 */ 232 string public name = "BeautyChain"; 233 string public symbol = "BEC"; 234 string public version = '1.0.0'; 235 uint8 public decimals = 18; 236 /** 237 * @dev Function to check the amount of tokens that an owner allowed to a spender. 238 */ 239 function BecToken() { 240 totalSupply = 7000000000 * (10**(uint256(decimals))); 241 balances[msg.sender] = totalSupply; // Give the creator all initial tokens 242 } 243 function () { 244 //if ether is sent to this address, send it back. 245 revert(); 246 } 247 } | 11+ assert(a == 0 || c / a == b); 20+ assert(b <= a); 24+ assert(c >= a); 51+ require(_to != address(0)); 51+ require(_value > 0 && _value <= balances[msg.sender]); 145+ require(msg.sender == owner); 152+ require(newOwner != address(0)); 168+ require(!paused); 174+ require(paused); | 174+ | require(paused); | |||||||||||||||||||||||
46 | 1 /** 2 *Submitted for verification at Etherscan.io on 2020-10-07 3 */ 4 // File: openzeppelin-solidity-2.3.0/contracts/ownership/Ownable.sol 5 pragma solidity ^0.5.0; 6 contract Bank{ 7 //reentrant here 8 function work(uint256 id, address goblin, uint256 loan, uint256 maxReturn, bytes calldata data) 9 external payable 10 onlyEOA accrue(msg.value) 11 { 12 // 1. Sanity check the input position, or add a new position of ID is 0. 13 if (id == 0) { 14 id = nextPositionID++; 15 positions[id].goblin = goblin; 16 positions[id].owner = msg.sender; 17 } else { 18 _; 19 } 20 emit Work(id, loan); 21 // 2. Make sure the goblin can accept more debt and remove the existing debt. 22 uint256 debt = _removeDebt(id).add(loan); 23 // 3. Perform the actual work, using a new scope to avoid stack-too-deep errors. 24 uint256 back; 25 { 26 uint256 sendETH = msg.value.add(loan); 27 require(sendETH <= address(this).balance, "insufficient ETH in the bank"); 28 uint256 beforeETH = address(this).balance.sub(sendETH); 29 Goblin(goblin).work.value(sendETH)(id, msg.sender, debt, data); 30 back = address(this).balance.sub(beforeETH); 31 } 32 // 4. Check and update position debt. 33 uint256 lessDebt = Math.min(debt, Math.min(back, maxReturn)); 34 debt = debt.sub(lessDebt); 35 if (debt > 0) { 36 uint256 health = Goblin(goblin).health(id); 37 uint256 workFactor = config.workFactor(goblin, debt); 38 _addDebt(id, debt); 39 } 40 // 5. Return excess ETH back. 41 if (back > lessDebt) SafeToken.safeTransferETH(msg.sender, back - lessDebt); 42 } 43 } | 17+ require(id < nextPositionID, "bad position id"); 17+ require(positions[id].goblin == goblin, "bad position goblin"); 17+ require(positions[id].owner == msg.sender, "not position owner"); 21+ require(config.isGoblin(goblin), "not a goblin"); 21+ require(loan == 0 || config.acceptDebt(goblin), "goblin not accept more debt"); 35+ require(debt >= config.minDebtSize(), "too small debt size"); 37+ require(health.mul(workFactor) >= debt.mul(10000), "bad work factor"); | 17+ | require(id < nextPositionID, "bad position id"); require(positions[id].goblin == goblin, "bad position goblin"); require(positions[id].owner == msg.sender, "not position owner"); | |||||||||||||||||||||||
47 | 1 /** 2 *Submitted for verification at Etherscan.io on 2020-10-07 3 */ 4 // File: openzeppelin-solidity-2.3.0/contracts/ownership/Ownable.sol 5 pragma solidity ^0.5.0; 6 contract Bank{ 7 //reentrant here 8 function work(uint256 id, address goblin, uint256 loan, uint256 maxReturn, bytes calldata data) 9 external payable 10 onlyEOA accrue(msg.value) 11 { 12 // 1. Sanity check the input position, or add a new position of ID is 0. 13 if (id == 0) { 14 id = nextPositionID++; 15 positions[id].goblin = goblin; 16 positions[id].owner = msg.sender; 17 } else { 18 _; 19 } 20 emit Work(id, loan); 21 // 2. Make sure the goblin can accept more debt and remove the existing debt. 22 uint256 debt = _removeDebt(id).add(loan); 23 // 3. Perform the actual work, using a new scope to avoid stack-too-deep errors. 24 uint256 back; 25 { 26 uint256 sendETH = msg.value.add(loan); 27 require(sendETH <= address(this).balance, "insufficient ETH in the bank"); 28 uint256 beforeETH = address(this).balance.sub(sendETH); 29 Goblin(goblin).work.value(sendETH)(id, msg.sender, debt, data); 30 back = address(this).balance.sub(beforeETH); 31 } 32 // 4. Check and update position debt. 33 uint256 lessDebt = Math.min(debt, Math.min(back, maxReturn)); 34 debt = debt.sub(lessDebt); 35 if (debt > 0) { 36 uint256 health = Goblin(goblin).health(id); 37 uint256 workFactor = config.workFactor(goblin, debt); 38 _addDebt(id, debt); 39 } 40 // 5. Return excess ETH back. 41 if (back > lessDebt) SafeToken.safeTransferETH(msg.sender, back - lessDebt); 42 } 43 } | 17+ require(id < nextPositionID, "bad position id"); 17+ require(positions[id].goblin == goblin, "bad position goblin"); 17+ require(positions[id].owner == msg.sender, "not position owner"); 21+ require(config.isGoblin(goblin), "not a goblin"); 21+ require(loan == 0 || config.acceptDebt(goblin), "goblin not accept more debt"); 35+ require(debt >= config.minDebtSize(), "too small debt size"); 37+ require(health.mul(workFactor) >= debt.mul(10000), "bad work factor"); | 21+ | require(config.isGoblin(goblin), "not a goblin"); require(loan == 0 || config.acceptDebt(goblin), "goblin not accept more debt"); | |||||||||||||||||||||||
48 | 1 /** 2 *Submitted for verification at Etherscan.io on 2020-10-07 3 */ 4 // File: openzeppelin-solidity-2.3.0/contracts/ownership/Ownable.sol 5 pragma solidity ^0.5.0; 6 contract Bank{ 7 //reentrant here 8 function work(uint256 id, address goblin, uint256 loan, uint256 maxReturn, bytes calldata data) 9 external payable 10 onlyEOA accrue(msg.value) 11 { 12 // 1. Sanity check the input position, or add a new position of ID is 0. 13 if (id == 0) { 14 id = nextPositionID++; 15 positions[id].goblin = goblin; 16 positions[id].owner = msg.sender; 17 } else { 18 _; 19 } 20 emit Work(id, loan); 21 // 2. Make sure the goblin can accept more debt and remove the existing debt. 22 uint256 debt = _removeDebt(id).add(loan); 23 // 3. Perform the actual work, using a new scope to avoid stack-too-deep errors. 24 uint256 back; 25 { 26 uint256 sendETH = msg.value.add(loan); 27 require(sendETH <= address(this).balance, "insufficient ETH in the bank"); 28 uint256 beforeETH = address(this).balance.sub(sendETH); 29 Goblin(goblin).work.value(sendETH)(id, msg.sender, debt, data); 30 back = address(this).balance.sub(beforeETH); 31 } 32 // 4. Check and update position debt. 33 uint256 lessDebt = Math.min(debt, Math.min(back, maxReturn)); 34 debt = debt.sub(lessDebt); 35 if (debt > 0) { 36 uint256 health = Goblin(goblin).health(id); 37 uint256 workFactor = config.workFactor(goblin, debt); 38 _addDebt(id, debt); 39 } 40 // 5. Return excess ETH back. 41 if (back > lessDebt) SafeToken.safeTransferETH(msg.sender, back - lessDebt); 42 } 43 } | 17+ require(id < nextPositionID, "bad position id"); 17+ require(positions[id].goblin == goblin, "bad position goblin"); 17+ require(positions[id].owner == msg.sender, "not position owner"); 21+ require(config.isGoblin(goblin), "not a goblin"); 21+ require(loan == 0 || config.acceptDebt(goblin), "goblin not accept more debt"); 35+ require(debt >= config.minDebtSize(), "too small debt size"); 37+ require(health.mul(workFactor) >= debt.mul(10000), "bad work factor"); | 35+ | require(debt >= config.minDebtSize(), "too small debt size"); | |||||||||||||||||||||||
49 | 1 /** 2 *Submitted for verification at Etherscan.io on 2020-10-07 3 */ 4 // File: openzeppelin-solidity-2.3.0/contracts/ownership/Ownable.sol 5 pragma solidity ^0.5.0; 6 contract Bank{ 7 //reentrant here 8 function work(uint256 id, address goblin, uint256 loan, uint256 maxReturn, bytes calldata data) 9 external payable 10 onlyEOA accrue(msg.value) 11 { 12 // 1. Sanity check the input position, or add a new position of ID is 0. 13 if (id == 0) { 14 id = nextPositionID++; 15 positions[id].goblin = goblin; 16 positions[id].owner = msg.sender; 17 } else { 18 _; 19 } 20 emit Work(id, loan); 21 // 2. Make sure the goblin can accept more debt and remove the existing debt. 22 uint256 debt = _removeDebt(id).add(loan); 23 // 3. Perform the actual work, using a new scope to avoid stack-too-deep errors. 24 uint256 back; 25 { 26 uint256 sendETH = msg.value.add(loan); 27 require(sendETH <= address(this).balance, "insufficient ETH in the bank"); 28 uint256 beforeETH = address(this).balance.sub(sendETH); 29 Goblin(goblin).work.value(sendETH)(id, msg.sender, debt, data); 30 back = address(this).balance.sub(beforeETH); 31 } 32 // 4. Check and update position debt. 33 uint256 lessDebt = Math.min(debt, Math.min(back, maxReturn)); 34 debt = debt.sub(lessDebt); 35 if (debt > 0) { 36 uint256 health = Goblin(goblin).health(id); 37 uint256 workFactor = config.workFactor(goblin, debt); 38 _addDebt(id, debt); 39 } 40 // 5. Return excess ETH back. 41 if (back > lessDebt) SafeToken.safeTransferETH(msg.sender, back - lessDebt); 42 } 43 } | 17+ require(id < nextPositionID, "bad position id"); 17+ require(positions[id].goblin == goblin, "bad position goblin"); 17+ require(positions[id].owner == msg.sender, "not position owner"); 21+ require(config.isGoblin(goblin), "not a goblin"); 21+ require(loan == 0 || config.acceptDebt(goblin), "goblin not accept more debt"); 35+ require(debt >= config.minDebtSize(), "too small debt size"); 37+ require(health.mul(workFactor) >= debt.mul(10000), "bad work factor"); | 37+ | require(health.mul(workFactor) >= debt.mul(10000), "bad work factor"); | |||||||||||||||||||||||
50 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 abstract contract ReentrancyGuard { 7 uint256 private constant _NOT_ENTERED = 1; 8 uint256 private constant _ENTERED = 2; 9 uint256 private _status; 10 constructor () { 11 _status = _NOT_ENTERED; 12 } 13 modifier nonReentrant() { 14 _status = _ENTERED; 15 _; 16 _status = _NOT_ENTERED; 17 } 18 } 19 contract surgeToken{ 20 /** Sells SURGE Tokens And Deposits the BNB into Seller's Address */ 21 function sell(uint256 tokenAmount) public nonReentrant returns (bool) { 22 address seller = msg.sender; 23 // make sure seller has this balance 24 require(_balances[seller] >= tokenAmount, 'cannot sell above token amount'); 25 // calculate the sell fee from this transaction 26 uint256 tokensToSwap = tokenAmount.mul(sellFee).div(10**2); 27 // how much BNB are these tokens worth? 28 uint256 amountBNB = tokensToSwap.mul(calculatePrice()); 29 //reentrant happens here: during call fallback, the attacker invoked purchase multiple times 30 (bool successful,) = payable(seller).call{value: amountBNB, gas: 40000}(""); 31 if (successful) { 32 // subtract full amount from sender 33 _balances[seller] = _balances[seller].sub(tokenAmount, 'sender does not have this amount to sell'); 34 // if successful, remove tokens from supply 35 _totalSupply = _totalSupply.sub(tokenAmount); 36 } else { 37 revert(); 38 } 39 emit Transfer(seller, address(this), tokenAmount); 40 return true; 41 } 42 function purchase(address buyer, uint256 bnbAmount) internal returns (bool) { 43 // make sure we don't buy more than the bnb in this contract 44 // previous amount of BNB before we received any 45 uint256 prevBNBAmount = (address(this).balance).sub(bnbAmount); 46 // if this is the first purchase, use current balance 47 prevBNBAmount = prevBNBAmount == 0 ? address(this).balance : prevBNBAmount; 48 // find the number of tokens we should mint to keep up with the current price 49 uint256 nShouldPurchase = hyperInflatePrice ? _totalSupply.mul(bnbAmount).div(address(this).balance) : _totalSupply.mul(bnbAmount).div(prevBNBAmount); 50 // apply our spread to tokens to inflate price relative to total supply 51 uint256 tokensToSend = nShouldPurchase.mul(spreadDivisor).div(10**2); 52 // revert if under 1 53 if (tokensToSend < 1) { 54 revert('Must Buy More Than One Surge'); 55 } 56 } 57 } | 13+ require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 44+ require(bnbAmount <= address(this).balance, 'purchase not included in balance'); | 13+ | require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); | |||||||||||||||||||||||
51 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 abstract contract ReentrancyGuard { 7 uint256 private constant _NOT_ENTERED = 1; 8 uint256 private constant _ENTERED = 2; 9 uint256 private _status; 10 constructor () { 11 _status = _NOT_ENTERED; 12 } 13 modifier nonReentrant() { 14 _status = _ENTERED; 15 _; 16 _status = _NOT_ENTERED; 17 } 18 } 19 contract surgeToken{ 20 /** Sells SURGE Tokens And Deposits the BNB into Seller's Address */ 21 function sell(uint256 tokenAmount) public nonReentrant returns (bool) { 22 address seller = msg.sender; 23 // make sure seller has this balance 24 require(_balances[seller] >= tokenAmount, 'cannot sell above token amount'); 25 // calculate the sell fee from this transaction 26 uint256 tokensToSwap = tokenAmount.mul(sellFee).div(10**2); 27 // how much BNB are these tokens worth? 28 uint256 amountBNB = tokensToSwap.mul(calculatePrice()); 29 //reentrant happens here: during call fallback, the attacker invoked purchase multiple times 30 (bool successful,) = payable(seller).call{value: amountBNB, gas: 40000}(""); 31 if (successful) { 32 // subtract full amount from sender 33 _balances[seller] = _balances[seller].sub(tokenAmount, 'sender does not have this amount to sell'); 34 // if successful, remove tokens from supply 35 _totalSupply = _totalSupply.sub(tokenAmount); 36 } else { 37 revert(); 38 } 39 emit Transfer(seller, address(this), tokenAmount); 40 return true; 41 } 42 function purchase(address buyer, uint256 bnbAmount) internal returns (bool) { 43 // make sure we don't buy more than the bnb in this contract 44 // previous amount of BNB before we received any 45 uint256 prevBNBAmount = (address(this).balance).sub(bnbAmount); 46 // if this is the first purchase, use current balance 47 prevBNBAmount = prevBNBAmount == 0 ? address(this).balance : prevBNBAmount; 48 // find the number of tokens we should mint to keep up with the current price 49 uint256 nShouldPurchase = hyperInflatePrice ? _totalSupply.mul(bnbAmount).div(address(this).balance) : _totalSupply.mul(bnbAmount).div(prevBNBAmount); 50 // apply our spread to tokens to inflate price relative to total supply 51 uint256 tokensToSend = nShouldPurchase.mul(spreadDivisor).div(10**2); 52 // revert if under 1 53 if (tokensToSend < 1) { 54 revert('Must Buy More Than One Surge'); 55 } 56 } 57 } | 13+ require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 44+ require(bnbAmount <= address(this).balance, 'purchase not included in balance'); | 44+ | require(bnbAmount <= address(this).balance, 'purchase not included in balance'); | |||||||||||||||||||||||
52 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 124+ | require(c >= a, "SafeMath: addition overflow"); | |||||||||||||||||||||||
53 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 137+ | return sub(a, b, "SafeMath: subtraction overflow"); | |||||||||||||||||||||||
54 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 150+ | require(b <= a, errorMessage); | |||||||||||||||||||||||
55 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 171+ | require(c / a == b, "SafeMath: multiplication overflow"); | |||||||||||||||||||||||
56 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 201+ | require(b > 0, errorMessage); | |||||||||||||||||||||||
57 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 233+ | require(b != 0, errorMessage); | |||||||||||||||||||||||
58 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 284+ | require(address(this).balance >= amount, "Address: insufficient balance"); | |||||||||||||||||||||||
59 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 286+ | require(success, "Address: unable to send value, recipient may have reverted"); | |||||||||||||||||||||||
60 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 338+ | require(address(this).balance >= value, "Address: insufficient balance for call"); | |||||||||||||||||||||||
61 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 341+ | require(isContract(target), "Address: call to non-contract"); | |||||||||||||||||||||||
62 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 544+ | require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); | |||||||||||||||||||||||
63 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 559+ | require(account != address(0), "ERC20: mint to the zero address"); | |||||||||||||||||||||||
64 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 576+ | require(account != address(0), "ERC20: burn from the zero address"); | |||||||||||||||||||||||
65 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 595+ | require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); | |||||||||||||||||||||||
66 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 655+ | require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); | |||||||||||||||||||||||
67 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 678+ | require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); | |||||||||||||||||||||||
68 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 715+ | require(_owner == _msgSender(), "Ownable: caller is not the owner"); | |||||||||||||||||||||||
69 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 733+ | require(newOwner != address(0), "Ownable: new owner is the zero address"); | |||||||||||||||||||||||
70 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 757+ | require(localCounter == _guardCounter); | |||||||||||||||||||||||
71 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 /** 7 *Submitted for verification at FtmScan.com on 2021-08-31 8 */ 9 // SPDX-License-Identifier: MIT 10 // File: @openzeppelin/contracts/GSN/Context.sol 11 pragma solidity ^0.5.0; 12 /* 13 * @dev Provides information about the current execution context, including the 14 * sender of the transaction and its data. While these are generally available 15 * via msg.sender and msg.data, they should not be accessed in such a direct 16 * manner, since when dealing with GSN meta-transactions the account sending and 17 * paying for execution may not be the actual sender (as far as an application 18 * is concerned). 19 * 20 * This contract is only required for intermediate, library-like contracts. 21 */ 22 abstract contract Context { 23 function _msgSender() internal view virtual returns (address payable) { 24 return msg.sender; 25 } 26 function _msgData() internal view virtual returns (bytes memory) { 27 this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 28 return msg.data; 29 } 30 } 31 // File: @openzeppelin/contracts/token/ERC20/IERC20.sol 32 /** 33 * @dev Interface of the ERC20 standard as defined in the EIP. 34 */ 35 interface IERC20 { 36 /** 37 * @dev Returns the amount of tokens in existence. 38 */ 39 function totalSupply() external view returns (uint256); 40 /** 41 * @dev Returns the amount of tokens owned by `account`. 42 */ 43 function balanceOf(address account) external view returns (uint256); 44 /** 45 * @dev Moves `amount` tokens from the caller's account to `recipient`. 46 * 47 * Returns a boolean value indicating whether the operation succeeded. 48 * 49 * Emits a {Transfer} event. 50 */ 51 function transfer(address recipient, uint256 amount) external returns (bool); 52 /** 53 * @dev Returns the remaining number of tokens that `spender` will be 54 * allowed to spend on behalf of `owner` through {transferFrom}. This is 55 * zero by default. 56 * 57 * This value changes when {approve} or {transferFrom} are called. 58 */ 59 function allowance(address owner, address spender) external view returns (uint256); 60 /** 61 * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. 62 * 63 * Returns a boolean value indicating whether the operation succeeded. 64 * 65 * IMPORTANT: Beware that changing an allowance with this method brings the risk 66 * that someone may use both the old and the new allowance by unfortunate 67 * transaction ordering. One possible solution to mitigate this race 68 * condition is to first reduce the spender's allowance to 0 and set the 69 * desired value afterwards: 70 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 71 * 72 * Emits an {Approval} event. 73 */ 74 function approve(address spender, uint256 amount) external returns (bool); 75 /** 76 * @dev Moves `amount` tokens from `sender` to `recipient` using the 77 * allowance mechanism. `amount` is then deducted from the caller's 78 * allowance. 79 * 80 * Returns a boolean value indicating whether the operation succeeded. 81 * 82 * Emits a {Transfer} event. 83 */ 84 function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); 85 /** 86 * @dev Emitted when `value` tokens are moved from one account (`from`) to 87 * another (`to`). 88 * 89 * Note that `value` may be zero. 90 */ 91 event Transfer(address indexed from, address indexed to, uint256 value); 92 /** 93 * @dev Emitted when the allowance of a `spender` for an `owner` is set by 94 * a call to {approve}. `value` is the new allowance. 95 */ 96 event Approval(address indexed owner, address indexed spender, uint256 value); 97 } 98 // File: @openzeppelin/contracts/math/SafeMath.sol 99 /** 100 * @dev Wrappers over Solidity's arithmetic operations with added overflow 101 * checks. 102 * 103 * Arithmetic operations in Solidity wrap on overflow. This can easily result 104 * in bugs, because programmers usually assume that an overflow raises an 105 * error, which is the standard behavior in high level programming languages. 106 * `SafeMath` restores this intuition by reverting the transaction when an 107 * operation overflows. 108 * 109 * Using this library instead of the unchecked operations eliminates an entire 110 * class of bugs, so it's recommended to use it always. 111 */ 112 library SafeMath { 113 /** 114 * @dev Returns the addition of two unsigned integers, reverting on 115 * overflow. 116 * 117 * Counterpart to Solidity's `+` operator. 118 * 119 * Requirements: 120 * 121 * - Addition cannot overflow. 122 */ 123 function add(uint256 a, uint256 b) internal pure returns (uint256) { 124 uint256 c = a + b; 125 return c; 126 } 127 /** 128 * @dev Returns the subtraction of two unsigned integers, reverting on 129 * overflow (when the result is negative). 130 * 131 * Counterpart to Solidity's `-` operator. 132 * 133 * Requirements: 134 * 135 * - Subtraction cannot overflow. 136 */ 137 function sub(uint256 a, uint256 b) internal pure returns (uint256) { 138 _; 139 } 140 /** 141 * @dev Returns the subtraction of two unsigned integers, reverting with custom message on 142 * overflow (when the result is negative). 143 * 144 * Counterpart to Solidity's `-` operator. 145 * 146 * Requirements: 147 * 148 * - Subtraction cannot overflow. 149 */ 150 function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 151 uint256 c = a - b; 152 return c; 153 } 154 /** 155 * @dev Returns the multiplication of two unsigned integers, reverting on 156 * overflow. 157 * 158 * Counterpart to Solidity's `*` operator. 159 * 160 * Requirements: 161 * 162 * - Multiplication cannot overflow. 163 */ 164 function mul(uint256 a, uint256 b) internal pure returns (uint256) { 165 // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 166 // benefit is lost if 'b' is also tested. 167 // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 168 if (a == 0) { 169 return 0; 170 } 171 uint256 c = a * b; 172 return c; 173 } 174 /** 175 * @dev Returns the integer division of two unsigned integers. Reverts on 176 * division by zero. The result is rounded towards zero. 177 * 178 * Counterpart to Solidity's `/` operator. Note: this function uses a 179 * `revert` opcode (which leaves remaining gas untouched) while Solidity 180 * uses an invalid opcode to revert (consuming all remaining gas). 181 * 182 * Requirements: 183 * 184 * - The divisor cannot be zero. 185 */ 186 function div(uint256 a, uint256 b) internal pure returns (uint256) { 187 _; 188 } 189 /** 190 * @dev Returns the integer division of two unsigned integers. Reverts with custom message on 191 * division by zero. The result is rounded towards zero. 192 * 193 * Counterpart to Solidity's `/` operator. Note: this function uses a 194 * `revert` opcode (which leaves remaining gas untouched) while Solidity 195 * uses an invalid opcode to revert (consuming all remaining gas). 196 * 197 * Requirements: 198 * 199 * - The divisor cannot be zero. 200 */ 201 function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 202 uint256 c = a / b; 203 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 204 return c; 205 } 206 /** 207 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 208 * Reverts when dividing by zero. 209 * 210 * Counterpart to Solidity's `%` operator. This function uses a `revert` 211 * opcode (which leaves remaining gas untouched) while Solidity uses an 212 * invalid opcode to revert (consuming all remaining gas). 213 * 214 * Requirements: 215 * 216 * - The divisor cannot be zero. 217 */ 218 function mod(uint256 a, uint256 b) internal pure returns (uint256) { 219 _; 220 } 221 /** 222 * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), 223 * Reverts with custom message when dividing by zero. 224 * 225 * Counterpart to Solidity's `%` operator. This function uses a `revert` 226 * opcode (which leaves remaining gas untouched) while Solidity uses an 227 * invalid opcode to revert (consuming all remaining gas). 228 * 229 * Requirements: 230 * 231 * - The divisor cannot be zero. 232 */ 233 function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { 234 return a % b; 235 } 236 } 237 // File: @openzeppelin/contracts/utils/Address.sol 238 /** 239 * @dev Collection of functions related to the address type 240 */ 241 library Address { 242 /** 243 * @dev Returns true if `account` is a contract. 244 * 245 * [IMPORTANT] 246 * ==== 247 * It is unsafe to assume that an address for which this function returns 248 * false is an externally-owned account (EOA) and not a contract. 249 * 250 * Among others, `isContract` will return false for the following 251 * types of addresses: 252 * 253 * - an externally-owned account 254 * - a contract in construction 255 * - an address where a contract will be created 256 * - an address where a contract lived, but was destroyed 257 * ==== 258 */ 259 function isContract(address account) internal view returns (bool) { 260 // This method relies in extcodesize, which returns 0 for contracts in 261 // construction, since the code is only stored at the end of the 262 // constructor execution. 263 uint256 size; 264 // solhint-disable-next-line no-inline-assembly 265 assembly { size := extcodesize(account) } 266 return size > 0; 267 } 268 /** 269 * @dev Replacement for Solidity's `transfer`: sends `amount` wei to 270 * `recipient`, forwarding all available gas and reverting on errors. 271 * 272 * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost 273 * of certain opcodes, possibly making contracts go over the 2300 gas limit 274 * imposed by `transfer`, making them unable to receive funds via 275 * `transfer`. {sendValue} removes this limitation. 276 * 277 * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. 278 * 279 * IMPORTANT: because control is transferred to `recipient`, care must be 280 * taken to not create reentrancy vulnerabilities. Consider using 281 * {ReentrancyGuard} or the 282 * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. 283 */ 284 function sendValue(address payable recipient, uint256 amount) internal { 285 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value 286 (bool success, ) = recipient.call{ value: amount }(""); 287 } 288 /** 289 * @dev Performs a Solidity function call using a low level `call`. A 290 * plain`call` is an unsafe replacement for a function call: use this 291 * function instead. 292 * 293 * If `target` reverts with a revert reason, it is bubbled up by this 294 * function (like regular Solidity function calls). 295 * 296 * Returns the raw returned data. To convert to the expected return value, 297 * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. 298 * 299 * Requirements: 300 * 301 * - `target` must be a contract. 302 * - calling `target` with `data` must not revert. 303 * 304 * _Available since v3.1._ 305 */ 306 function functionCall(address target, bytes memory data) internal returns (bytes memory) { 307 return functionCall(target, data, "Address: low-level call failed"); 308 } 309 /** 310 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with 311 * `errorMessage` as a fallback revert reason when `target` reverts. 312 * 313 * _Available since v3.1._ 314 */ 315 function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { 316 return _functionCallWithValue(target, data, 0, errorMessage); 317 } 318 /** 319 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], 320 * but also transferring `value` wei to `target`. 321 * 322 * Requirements: 323 * 324 * - the calling contract must have an ETH balance of at least `value`. 325 * - the called Solidity function must be `payable`. 326 * 327 * _Available since v3.1._ 328 */ 329 function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { 330 return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); 331 } 332 /** 333 * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but 334 * with `errorMessage` as a fallback revert reason when `target` reverts. 335 * 336 * _Available since v3.1._ 337 */ 338 function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { 339 return _functionCallWithValue(target, data, value, errorMessage); 340 } 341 function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { 342 // solhint-disable-next-line avoid-low-level-calls 343 (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 344 if (success) { 345 return returndata; 346 } else { 347 // Look for revert reason and bubble it up if present 348 if (returndata.length > 0) { 349 // The easiest way to bubble the revert reason is using memory via assembly 350 // solhint-disable-next-line no-inline-assembly 351 assembly { 352 let returndata_size := mload(returndata) 353 revert(add(32, returndata), returndata_size) 354 } 355 } else { 356 revert(errorMessage); 357 } 358 } 359 } 360 } 361 // File: @openzeppelin/contracts/token/ERC20/ERC20.sol 362 /** 363 * @dev Implementation of the {IERC20} interface. 364 * 365 * This implementation is agnostic to the way tokens are created. This means 366 * that a supply mechanism has to be added in a derived contract using {_mint}. 367 * For a generic mechanism see {ERC20PresetMinterPauser}. 368 * 369 * TIP: For a detailed writeup see our guide 370 * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How 371 * to implement supply mechanisms]. 372 * 373 * We have followed general OpenZeppelin guidelines: functions revert instead 374 * of returning `false` on failure. This behavior is nonetheless conventional 375 * and does not conflict with the expectations of ERC20 applications. 376 * 377 * Additionally, an {Approval} event is emitted on calls to {transferFrom}. 378 * This allows applications to reconstruct the allowance for all accounts just 379 * by listening to said events. Other implementations of the EIP may not emit 380 * these events, as it isn't required by the specification. 381 * 382 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} 383 * functions have been added to mitigate the well-known issues around setting 384 * allowances. See {IERC20-approve}. 385 */ 386 contract ERC20 is Context, IERC20 { 387 using SafeMath for uint256; 388 using Address for address; 389 mapping (address => uint256) private _balances; 390 mapping (address => mapping (address => uint256)) private _allowances; 391 uint256 private _totalSupply; 392 string private _name; 393 string private _symbol; 394 uint8 private _decimals; 395 /** 396 * @dev Sets the values for {name} and {symbol}, initializes {decimals} with 397 * a default value of 18. 398 * 399 * To select a different value for {decimals}, use {_setupDecimals}. 400 * 401 * All three of these values are immutable: they can only be set once during 402 * construction. 403 */ 404 constructor (string memory name, string memory symbol) public { 405 _name = name; 406 _symbol = symbol; 407 _decimals = 18; 408 } 409 /** 410 * @dev Returns the name of the token. 411 */ 412 function name() public view returns (string memory) { 413 return _name; 414 } 415 /** 416 * @dev Returns the symbol of the token, usually a shorter version of the 417 * name. 418 */ 419 function symbol() public view returns (string memory) { 420 return _symbol; 421 } 422 /** 423 * @dev Returns the number of decimals used to get its user representation. 424 * For example, if `decimals` equals `2`, a balance of `505` tokens should 425 * be displayed to a user as `5,05` (`505 / 10 ** 2`). 426 * 427 * Tokens usually opt for a value of 18, imitating the relationship between 428 * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is 429 * called. 430 * 431 * NOTE: This information is only used for _display_ purposes: it in 432 * no way affects any of the arithmetic of the contract, including 433 * {IERC20-balanceOf} and {IERC20-transfer}. 434 */ 435 function decimals() public view returns (uint8) { 436 return _decimals; 437 } 438 /** 439 * @dev See {IERC20-totalSupply}. 440 */ 441 function totalSupply() public view override returns (uint256) { 442 return _totalSupply; 443 } 444 /** 445 * @dev See {IERC20-balanceOf}. 446 */ 447 function balanceOf(address account) public view override returns (uint256) { 448 return _balances[account]; 449 } 450 /** 451 * @dev See {IERC20-transfer}. 452 * 453 * Requirements: 454 * 455 * - `recipient` cannot be the zero address. 456 * - the caller must have a balance of at least `amount`. 457 */ 458 function transfer(address recipient, uint256 amount) public virtual override returns (bool) { 459 _transfer(_msgSender(), recipient, amount); 460 return true; 461 } 462 /** 463 * @dev See {IERC20-allowance}. 464 */ 465 function allowance(address owner, address spender) public view virtual override returns (uint256) { 466 return _allowances[owner][spender]; 467 } 468 /** 469 * @dev See {IERC20-approve}. 470 * 471 * Requirements: 472 * 473 * - `spender` cannot be the zero address. 474 */ 475 function approve(address spender, uint256 amount) public virtual override returns (bool) { 476 _approve(_msgSender(), spender, amount); 477 return true; 478 } 479 /** 480 * @dev See {IERC20-transferFrom}. 481 * 482 * Emits an {Approval} event indicating the updated allowance. This is not 483 * required by the EIP. See the note at the beginning of {ERC20}; 484 * 485 * Requirements: 486 * - `sender` and `recipient` cannot be the zero address. 487 * - `sender` must have a balance of at least `amount`. 488 * - the caller must have allowance for ``sender``'s tokens of at least 489 * `amount`. 490 */ 491 function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { 492 _transfer(sender, recipient, amount); 493 _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); 494 return true; 495 } 496 /** 497 * @dev Atomically increases the allowance granted to `spender` by the caller. 498 * 499 * This is an alternative to {approve} that can be used as a mitigation for 500 * problems described in {IERC20-approve}. 501 * 502 * Emits an {Approval} event indicating the updated allowance. 503 * 504 * Requirements: 505 * 506 * - `spender` cannot be the zero address. 507 */ 508 function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { 509 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); 510 return true; 511 } 512 /** 513 * @dev Atomically decreases the allowance granted to `spender` by the caller. 514 * 515 * This is an alternative to {approve} that can be used as a mitigation for 516 * problems described in {IERC20-approve}. 517 * 518 * Emits an {Approval} event indicating the updated allowance. 519 * 520 * Requirements: 521 * 522 * - `spender` cannot be the zero address. 523 * - `spender` must have allowance for the caller of at least 524 * `subtractedValue`. 525 */ 526 function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { 527 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); 528 return true; 529 } 530 /** 531 * @dev Moves tokens `amount` from `sender` to `recipient`. 532 * 533 * This is internal function is equivalent to {transfer}, and can be used to 534 * e.g. implement automatic token fees, slashing mechanisms, etc. 535 * 536 * Emits a {Transfer} event. 537 * 538 * Requirements: 539 * 540 * - `sender` cannot be the zero address. 541 * - `recipient` cannot be the zero address. 542 * - `sender` must have a balance of at least `amount`. 543 */ 544 function _transfer(address sender, address recipient, uint256 amount) internal virtual { 545 _beforeTokenTransfer(sender, recipient, amount); 546 _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); 547 _balances[recipient] = _balances[recipient].add(amount); 548 emit Transfer(sender, recipient, amount); 549 } 550 /** @dev Creates `amount` tokens and assigns them to `account`, increasing 551 * the total supply. 552 * 553 * Emits a {Transfer} event with `from` set to the zero address. 554 * 555 * Requirements 556 * 557 * - `to` cannot be the zero address. 558 */ 559 function _mint(address account, uint256 amount) internal virtual { 560 _beforeTokenTransfer(address(0), account, amount); 561 _totalSupply = _totalSupply.add(amount); 562 _balances[account] = _balances[account].add(amount); 563 emit Transfer(address(0), account, amount); 564 } 565 /** 566 * @dev Destroys `amount` tokens from `account`, reducing the 567 * total supply. 568 * 569 * Emits a {Transfer} event with `to` set to the zero address. 570 * 571 * Requirements 572 * 573 * - `account` cannot be the zero address. 574 * - `account` must have at least `amount` tokens. 575 */ 576 function _burn(address account, uint256 amount) internal virtual { 577 _beforeTokenTransfer(account, address(0), amount); 578 _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); 579 _totalSupply = _totalSupply.sub(amount); 580 emit Transfer(account, address(0), amount); 581 } 582 /** 583 * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. 584 * 585 * This internal function is equivalent to `approve`, and can be used to 586 * e.g. set automatic allowances for certain subsystems, etc. 587 * 588 * Emits an {Approval} event. 589 * 590 * Requirements: 591 * 592 * - `owner` cannot be the zero address. 593 * - `spender` cannot be the zero address. 594 */ 595 function _approve(address owner, address spender, uint256 amount) internal virtual { 596 _allowances[owner][spender] = amount; 597 emit Approval(owner, spender, amount); 598 } 599 /** 600 * @dev Sets {decimals} to a value other than the default one of 18. 601 * 602 * WARNING: This function should only be called from the constructor. Most 603 * applications that interact with token contracts will not expect 604 * {decimals} to ever change, and may work incorrectly if it does. 605 */ 606 function _setupDecimals(uint8 decimals_) internal { 607 _decimals = decimals_; 608 } 609 /** 610 * @dev Hook that is called before any transfer of tokens. This includes 611 * minting and burning. 612 * 613 * Calling conditions: 614 * 615 * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens 616 * will be to transferred to `to`. 617 * - when `from` is zero, `amount` tokens will be minted for `to`. 618 * - when `to` is zero, `amount` of ``from``'s tokens will be burned. 619 * - `from` and `to` are never both zero. 620 * 621 * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. 622 */ 623 function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } 624 } 625 // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol 626 /** 627 * @title SafeERC20 628 * @dev Wrappers around ERC20 operations that throw on failure (when the token 629 * contract returns false). Tokens that return no value (and instead revert or 630 * throw on failure) are also supported, non-reverting calls are assumed to be 631 * successful. 632 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, 633 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. 634 */ 635 library SafeERC20 { 636 using SafeMath for uint256; 637 using Address for address; 638 function safeTransfer(IERC20 token, address to, uint256 value) internal { 639 _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); 640 } 641 function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { 642 _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); 643 } 644 /** 645 * @dev Deprecated. This function has issues similar to the ones found in 646 * {IERC20-approve}, and its usage is discouraged. 647 * 648 * Whenever possible, use {safeIncreaseAllowance} and 649 * {safeDecreaseAllowance} instead. 650 */ 651 function safeApprove(IERC20 token, address spender, uint256 value) internal { 652 // safeApprove should only be called when setting an initial allowance, 653 // or when resetting it to zero. To increase and decrease it, use 654 // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' 655 // solhint-disable-next-line max-line-length 656 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); 657 } 658 function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { 659 uint256 newAllowance = token.allowance(address(this), spender).add(value); 660 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 661 } 662 function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { 663 uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); 664 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); 665 } 666 /** 667 * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement 668 * on the return value: the return value is optional (but if data is returned, it must not be false). 669 * @param token The token targeted by the call. 670 * @param data The call data (encoded using abi.encode or one of its variants). 671 */ 672 function _callOptionalReturn(IERC20 token, bytes memory data) private { 673 // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since 674 // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that 675 // the target address contains contract code and also asserts for success in the low-level call. 676 bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed in vault"); 677 if (returndata.length > 0) { // Return data is optional 678 // solhint-disable-next-line max-line-length 679 } 680 } 681 } 682 // File: @openzeppelin/contracts/access/Ownable.sol 683 /** 684 * @dev Contract module which provides a basic access control mechanism, where 685 * there is an account (an owner) that can be granted exclusive access to 686 * specific functions. 687 * 688 * By default, the owner account will be the one that deploys the contract. This 689 * can later be changed with {transferOwnership}. 690 * 691 * This module is used through inheritance. It will make available the modifier 692 * `onlyOwner`, which can be applied to your functions to restrict their use to 693 * the owner. 694 */ 695 contract Ownable is Context { 696 address private _owner; 697 event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); 698 /** 699 * @dev Initializes the contract setting the deployer as the initial owner. 700 */ 701 constructor () internal { 702 address msgSender = _msgSender(); 703 _owner = msgSender; 704 emit OwnershipTransferred(address(0), msgSender); 705 } 706 /** 707 * @dev Returns the address of the current owner. 708 */ 709 function owner() public view returns (address) { 710 return _owner; 711 } 712 /** 713 * @dev Throws if called by any account other than the owner. 714 */ 715 modifier onlyOwner() { 716 _; 717 } 718 /** 719 * @dev Leaves the contract without owner. It will not be possible to call 720 * `onlyOwner` functions anymore. Can only be called by the current owner. 721 * 722 * NOTE: Renouncing ownership will leave the contract without an owner, 723 * thereby removing any functionality that is only available to the owner. 724 */ 725 function renounceOwnership() public virtual onlyOwner { 726 emit OwnershipTransferred(_owner, address(0)); 727 _owner = address(0); 728 } 729 /** 730 * @dev Transfers ownership of the contract to a new account (`newOwner`). 731 * Can only be called by the current owner. 732 */ 733 function transferOwnership(address newOwner) public virtual onlyOwner { 734 emit OwnershipTransferred(_owner, newOwner); 735 _owner = newOwner; 736 } 737 } 738 /** 739 * @title Helps contracts guard against reentrancy attacks. 740 * @author Remco Bloemen <remco@2π.com>, Eenae <alexey@mixbytes.io> 741 * @dev If you mark a function `nonReentrant`, you should also 742 * mark it `external`. 743 */ 744 contract ReentrancyGuard { 745 /// @dev counter to allow mutex lock with only one SSTORE operation 746 uint256 private _guardCounter = 1; 747 /** 748 * @dev Prevents a contract from calling itself, directly or indirectly. 749 * If you mark a function `nonReentrant`, you should also 750 * mark it `external`. Calling one `nonReentrant` function from 751 * another is not supported. Instead, you can implement a 752 * `private` function doing the actual work, and an `external` 753 * wrapper marked as `nonReentrant`. 754 */ 755 modifier nonReentrant() { 756 _guardCounter += 1; 757 uint256 localCounter = _guardCounter; 758 _; 759 } 760 } 761 interface IStrategy { 762 function vault() external view returns (address); 763 function want() external view returns (IERC20); 764 function beforeDeposit() external; 765 function deposit() external; 766 function withdraw(uint256) external; 767 function balanceOfPool() external view returns (uint256); 768 function harvest() external; 769 function retireStrat() external; 770 function panic() external; 771 function pause() external; 772 function unpause() external; 773 function paused() external view returns (bool); 774 } 775 /** 776 * @dev Implementation of a vault to deposit funds for yield optimizing. 777 * This is the contract that receives funds and that users interface with. 778 * The yield optimizing strategy itself is implemented in a separate 'Strategy.sol' contract. 779 */ 780 contract GrimBoostVault is ERC20, Ownable, ReentrancyGuard { 781 using SafeERC20 for IERC20; 782 using SafeMath for uint256; 783 struct StratCandidate { 784 address implementation; 785 uint proposedTime; 786 } 787 // The last proposed strategy to switch to. 788 StratCandidate public stratCandidate; 789 // The strategy currently in use by the vault. 790 IStrategy public strategy; 791 // The minimum time it has to pass before a strat candidate can be approved. 792 uint256 public immutable approvalDelay; 793 event NewStratCandidate(address implementation); 794 event UpgradeStrat(address implementation); 795 //this is the buggy functon: the attacker inserts his/her own addr at token, which containn 796 //depositFor() loop 797 function depositFor(address token, uint _amount,address user ) public { 798 uint256 _pool = balance(); 799 IERC20(token).safeTransferFrom(msg.sender, address(this), _amount); 800 earn(); 801 uint256 _after = balance(); 802 _amount = _after.sub(_pool); // Additional check for deflationary tokens 803 uint256 shares = 0; 804 if (totalSupply() == 0) { 805 shares = _amount; 806 } else { 807 shares = (_amount.mul(totalSupply())).div(_pool); 808 } 809 _mint(user, shares); 810 } 811 } | 124+ require(c >= a, "SafeMath: addition overflow"); 137+ return sub(a, b, "SafeMath: subtraction overflow"); 150+ require(b <= a, errorMessage); 171+ require(c / a == b, "SafeMath: multiplication overflow"); 201+ require(b > 0, errorMessage); 233+ require(b != 0, errorMessage); 284+ require(address(this).balance >= amount, "Address: insufficient balance"); 286+ require(success, "Address: unable to send value, recipient may have reverted"); 338+ require(address(this).balance >= value, "Address: insufficient balance for call"); 341+ require(isContract(target), "Address: call to non-contract"); 544+ require(sender != address(0), "ERC20: transfer from the zero address"); 544+ require(recipient != address(0), "ERC20: transfer to the zero address"); 559+ require(account != address(0), "ERC20: mint to the zero address"); 576+ require(account != address(0), "ERC20: burn from the zero address"); 595+ require(owner != address(0), "ERC20: approve from the zero address"); 595+ require(spender != address(0), "ERC20: approve to the zero address"); 655+ require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); 678+ require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); 715+ require(_owner == _msgSender(), "Ownable: caller is not the owner"); 733+ require(newOwner != address(0), "Ownable: new owner is the zero address"); 757+ require(localCounter == _guardCounter); 797+ assert(token != address(this)); 797+ assert(token != user); | 797+ | assert(token != address(this)); assert(token != user); | |||||||||||||||||||||||
72 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 abstract contract ReentrancyGuard { 7 uint256 private constant _NOT_ENTERED = 1; 8 uint256 private constant _ENTERED = 2; 9 uint256 private _status; 10 constructor () { 11 _status = _NOT_ENTERED; 12 } 13 modifier nonReentrant() { 14 _status = _ENTERED; 15 _; 16 _status = _NOT_ENTERED; 17 } 18 } 19 contract surgeToken{ 20 /** Sells SURGE Tokens And Deposits the BNB into Seller's Address */ 21 function sell(uint256 tokenAmount) public nonReentrant returns (bool) { 22 address seller = msg.sender; 23 // make sure seller has this balance 24 // calculate the sell fee from this transaction 25 uint256 tokensToSwap = tokenAmount.mul(sellFee).div(10**2); 26 // how much BNB are these tokens worth? 27 uint256 amountBNB = tokensToSwap.mul(calculatePrice()); 28 //reentrant happens here: during call fallback, the attacker invoked purchase multiple times 29 (bool successful,) = payable(seller).call{value: amountBNB, gas: 40000}(""); 30 if (successful) { 31 // subtract full amount from sender 32 _balances[seller] = _balances[seller].sub(tokenAmount, 'sender does not have this amount to sell'); 33 // if successful, remove tokens from supply 34 _totalSupply = _totalSupply.sub(tokenAmount); 35 } else { 36 revert(); 37 } 38 emit Transfer(seller, address(this), tokenAmount); 39 return true; 40 } 41 function purchase(address buyer, uint256 bnbAmount) internal returns (bool) { 42 // make sure we don't buy more than the bnb in this contract 43 // previous amount of BNB before we received any 44 uint256 prevBNBAmount = (address(this).balance).sub(bnbAmount); 45 // if this is the first purchase, use current balance 46 prevBNBAmount = prevBNBAmount == 0 ? address(this).balance : prevBNBAmount; 47 // find the number of tokens we should mint to keep up with the current price 48 uint256 nShouldPurchase = hyperInflatePrice ? _totalSupply.mul(bnbAmount).div(address(this).balance) : _totalSupply.mul(bnbAmount).div(prevBNBAmount); 49 // apply our spread to tokens to inflate price relative to total supply 50 uint256 tokensToSend = nShouldPurchase.mul(spreadDivisor).div(10**2); 51 // revert if under 1 52 if (tokensToSend < 1) { 53 revert('Must Buy More Than One Surge'); 54 } 55 } 56 } | 13+ require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 23+ require(_balances[seller] >= tokenAmount, 'cannot sell above token amount'); 42+ require(bnbAmount <= address(this).balance, 'purchase not included in balance'); | 13+ | require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); | |||||||||||||||||||||||
73 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 abstract contract ReentrancyGuard { 7 uint256 private constant _NOT_ENTERED = 1; 8 uint256 private constant _ENTERED = 2; 9 uint256 private _status; 10 constructor () { 11 _status = _NOT_ENTERED; 12 } 13 modifier nonReentrant() { 14 _status = _ENTERED; 15 _; 16 _status = _NOT_ENTERED; 17 } 18 } 19 contract surgeToken{ 20 /** Sells SURGE Tokens And Deposits the BNB into Seller's Address */ 21 function sell(uint256 tokenAmount) public nonReentrant returns (bool) { 22 address seller = msg.sender; 23 // make sure seller has this balance 24 // calculate the sell fee from this transaction 25 uint256 tokensToSwap = tokenAmount.mul(sellFee).div(10**2); 26 // how much BNB are these tokens worth? 27 uint256 amountBNB = tokensToSwap.mul(calculatePrice()); 28 //reentrant happens here: during call fallback, the attacker invoked purchase multiple times 29 (bool successful,) = payable(seller).call{value: amountBNB, gas: 40000}(""); 30 if (successful) { 31 // subtract full amount from sender 32 _balances[seller] = _balances[seller].sub(tokenAmount, 'sender does not have this amount to sell'); 33 // if successful, remove tokens from supply 34 _totalSupply = _totalSupply.sub(tokenAmount); 35 } else { 36 revert(); 37 } 38 emit Transfer(seller, address(this), tokenAmount); 39 return true; 40 } 41 function purchase(address buyer, uint256 bnbAmount) internal returns (bool) { 42 // make sure we don't buy more than the bnb in this contract 43 // previous amount of BNB before we received any 44 uint256 prevBNBAmount = (address(this).balance).sub(bnbAmount); 45 // if this is the first purchase, use current balance 46 prevBNBAmount = prevBNBAmount == 0 ? address(this).balance : prevBNBAmount; 47 // find the number of tokens we should mint to keep up with the current price 48 uint256 nShouldPurchase = hyperInflatePrice ? _totalSupply.mul(bnbAmount).div(address(this).balance) : _totalSupply.mul(bnbAmount).div(prevBNBAmount); 49 // apply our spread to tokens to inflate price relative to total supply 50 uint256 tokensToSend = nShouldPurchase.mul(spreadDivisor).div(10**2); 51 // revert if under 1 52 if (tokensToSend < 1) { 53 revert('Must Buy More Than One Surge'); 54 } 55 } 56 } | 13+ require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 23+ require(_balances[seller] >= tokenAmount, 'cannot sell above token amount'); 42+ require(bnbAmount <= address(this).balance, 'purchase not included in balance'); | 23+ | require(_balances[seller] >= tokenAmount, 'cannot sell above token amount'); | |||||||||||||||||||||||
74 | 1 /** 2 *Submitted for verification at BscScan.com on 2021-07-30 3 */ 4 //SPDX-License-Identifier: MIT 5 pragma solidity ^0.8.0; 6 abstract contract ReentrancyGuard { 7 uint256 private constant _NOT_ENTERED = 1; 8 uint256 private constant _ENTERED = 2; 9 uint256 private _status; 10 constructor () { 11 _status = _NOT_ENTERED; 12 } 13 modifier nonReentrant() { 14 _status = _ENTERED; 15 _; 16 _status = _NOT_ENTERED; 17 } 18 } 19 contract surgeToken{ 20 /** Sells SURGE Tokens And Deposits the BNB into Seller's Address */ 21 function sell(uint256 tokenAmount) public nonReentrant returns (bool) { 22 address seller = msg.sender; 23 // make sure seller has this balance 24 // calculate the sell fee from this transaction 25 uint256 tokensToSwap = tokenAmount.mul(sellFee).div(10**2); 26 // how much BNB are these tokens worth? 27 uint256 amountBNB = tokensToSwap.mul(calculatePrice()); 28 //reentrant happens here: during call fallback, the attacker invoked purchase multiple times 29 (bool successful,) = payable(seller).call{value: amountBNB, gas: 40000}(""); 30 if (successful) { 31 // subtract full amount from sender 32 _balances[seller] = _balances[seller].sub(tokenAmount, 'sender does not have this amount to sell'); 33 // if successful, remove tokens from supply 34 _totalSupply = _totalSupply.sub(tokenAmount); 35 } else { 36 revert(); 37 } 38 emit Transfer(seller, address(this), tokenAmount); 39 return true; 40 } 41 function purchase(address buyer, uint256 bnbAmount) internal returns (bool) { 42 // make sure we don't buy more than the bnb in this contract 43 // previous amount of BNB before we received any 44 uint256 prevBNBAmount = (address(this).balance).sub(bnbAmount); 45 // if this is the first purchase, use current balance 46 prevBNBAmount = prevBNBAmount == 0 ? address(this).balance : prevBNBAmount; 47 // find the number of tokens we should mint to keep up with the current price 48 uint256 nShouldPurchase = hyperInflatePrice ? _totalSupply.mul(bnbAmount).div(address(this).balance) : _totalSupply.mul(bnbAmount).div(prevBNBAmount); 49 // apply our spread to tokens to inflate price relative to total supply 50 uint256 tokensToSend = nShouldPurchase.mul(spreadDivisor).div(10**2); 51 // revert if under 1 52 if (tokensToSend < 1) { 53 revert('Must Buy More Than One Surge'); 54 } 55 } 56 } | 13+ require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); 23+ require(_balances[seller] >= tokenAmount, 'cannot sell above token amount'); 42+ require(bnbAmount <= address(this).balance, 'purchase not included in balance'); | 42+ | require(bnbAmount <= address(this).balance, 'purchase not included in balance'); | |||||||||||||||||||||||
75 | 1 // Sources flattened with hardhat v2.1.2 https://hardhat.org 2 // File contracts/v0.4/token/linkERC20Basic.sol 3 pragma solidity ^0.4.11; 4 /** 5 * @title ERC20Basic 6 * @dev Simpler version of ERC20 interface 7 * @dev see https://github.com/ethereum/EIPs/issues/179 8 */ 9 contract linkERC20Basic { 10 uint256 public totalSupply; 11 function balanceOf(address who) constant returns (uint256); 12 function transfer(address to, uint256 value) returns (bool); 13 event Transfer(address indexed from, address indexed to, uint256 value); 14 } 15 // File contracts/v0.4/token/linkERC20.sol 16 /** 17 * @title ERC20 interface 18 * @dev see https://github.com/ethereum/EIPs/issues/20 19 */ 20 contract linkERC20 is linkERC20Basic { 21 function allowance(address owner, address spender) constant returns (uint256); 22 function transferFrom(address from, address to, uint256 value) returns (bool); 23 function approve(address spender, uint256 value) returns (bool); 24 event Approval(address indexed owner, address indexed spender, uint256 value); 25 } 26 // File contracts/v0.4/token/ERC677.sol 27 contract ERC677 is linkERC20 { 28 function transferAndCall(address to, uint value, bytes data) returns (bool success); 29 event Transfer(address indexed from, address indexed to, uint value, bytes data); 30 } 31 // File contracts/v0.4/token/ERC677Receiver.sol 32 contract ERC677Receiver { 33 function onTokenTransfer(address _sender, uint _value, bytes _data); 34 } 35 // File contracts/v0.4/ERC677Token.sol 36 contract ERC677Token is ERC677 { 37 /** 38 * @dev transfer token to a contract address with additional data if the recipient is a contact. 39 * @param _to The address to transfer to. 40 * @param _value The amount to be transferred. 41 * @param _data The extra data to be passed to the receiving contract. 42 */ 43 function transferAndCall(address _to, uint _value, bytes _data) 44 public 45 returns (bool success) 46 { 47 super.transfer(_to, _value); 48 Transfer(msg.sender, _to, _value, _data); 49 if (isContract(_to)) { 50 contractFallback(_to, _value, _data); 51 } 52 return true; 53 } 54 // PRIVATE 55 //bug: this is the buggy fall back that allows reentrancy 56 function contractFallback(address _to, uint _value, bytes _data) 57 private 58 { 59 ERC677Receiver receiver = ERC677Receiver(_to); 60 receiver.onTokenTransfer(msg.sender, _value, _data); 61 } 62 function isContract(address _addr) 63 private 64 returns (bool hasCode) 65 { 66 uint length; 67 assembly { length := extcodesize(_addr) } 68 return length > 0; 69 } 70 } 71 abstract contract CToken { 72 function doTransferOut(address payable to, uint amount) virtual internal; 73 doTransferOut(borrower, borrowAmount); 74 /* We write the previously calculated values into storage */ 75 accountBorrows[borrower].principal = vars.accountBorrowsNew; 76 accountBorrows[borrower].interestIndex = borrowIndex; 77 totalBorrows = vars.totalBorrowsNew; 78 /* We emit a Borrow event */ 79 emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew); 80 } 81 // File contracts/v0.4/math/linkSafeMath.sol 82 /** 83 * @title SafeMath 84 * @dev Math operations with safety checks that throw on error 85 */ 86 library linkSafeMath { 87 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 88 uint256 c = a * b; 89 return c; 90 } 91 function div(uint256 a, uint256 b) internal constant returns (uint256) { 92 // assert(b > 0); // Solidity automatically throws when dividing by 0 93 uint256 c = a / b; 94 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 95 return c; 96 } 97 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 98 return a - b; 99 } 100 function add(uint256 a, uint256 b) internal constant returns (uint256) { 101 uint256 c = a + b; 102 return c; 103 } 104 } | 88+ assert(a == 0 || c / a == b); 97+ assert(b <= a); 101+ assert(c >= a); | 88+ | assert(a == 0 || c / a == b); | |||||||||||||||||||||||
76 | 1 // Sources flattened with hardhat v2.1.2 https://hardhat.org 2 // File contracts/v0.4/token/linkERC20Basic.sol 3 pragma solidity ^0.4.11; 4 /** 5 * @title ERC20Basic 6 * @dev Simpler version of ERC20 interface 7 * @dev see https://github.com/ethereum/EIPs/issues/179 8 */ 9 contract linkERC20Basic { 10 uint256 public totalSupply; 11 function balanceOf(address who) constant returns (uint256); 12 function transfer(address to, uint256 value) returns (bool); 13 event Transfer(address indexed from, address indexed to, uint256 value); 14 } 15 // File contracts/v0.4/token/linkERC20.sol 16 /** 17 * @title ERC20 interface 18 * @dev see https://github.com/ethereum/EIPs/issues/20 19 */ 20 contract linkERC20 is linkERC20Basic { 21 function allowance(address owner, address spender) constant returns (uint256); 22 function transferFrom(address from, address to, uint256 value) returns (bool); 23 function approve(address spender, uint256 value) returns (bool); 24 event Approval(address indexed owner, address indexed spender, uint256 value); 25 } 26 // File contracts/v0.4/token/ERC677.sol 27 contract ERC677 is linkERC20 { 28 function transferAndCall(address to, uint value, bytes data) returns (bool success); 29 event Transfer(address indexed from, address indexed to, uint value, bytes data); 30 } 31 // File contracts/v0.4/token/ERC677Receiver.sol 32 contract ERC677Receiver { 33 function onTokenTransfer(address _sender, uint _value, bytes _data); 34 } 35 // File contracts/v0.4/ERC677Token.sol 36 contract ERC677Token is ERC677 { 37 /** 38 * @dev transfer token to a contract address with additional data if the recipient is a contact. 39 * @param _to The address to transfer to. 40 * @param _value The amount to be transferred. 41 * @param _data The extra data to be passed to the receiving contract. 42 */ 43 function transferAndCall(address _to, uint _value, bytes _data) 44 public 45 returns (bool success) 46 { 47 super.transfer(_to, _value); 48 Transfer(msg.sender, _to, _value, _data); 49 if (isContract(_to)) { 50 contractFallback(_to, _value, _data); 51 } 52 return true; 53 } 54 // PRIVATE 55 //bug: this is the buggy fall back that allows reentrancy 56 function contractFallback(address _to, uint _value, bytes _data) 57 private 58 { 59 ERC677Receiver receiver = ERC677Receiver(_to); 60 receiver.onTokenTransfer(msg.sender, _value, _data); 61 } 62 function isContract(address _addr) 63 private 64 returns (bool hasCode) 65 { 66 uint length; 67 assembly { length := extcodesize(_addr) } 68 return length > 0; 69 } 70 } 71 abstract contract CToken { 72 function doTransferOut(address payable to, uint amount) virtual internal; 73 doTransferOut(borrower, borrowAmount); 74 /* We write the previously calculated values into storage */ 75 accountBorrows[borrower].principal = vars.accountBorrowsNew; 76 accountBorrows[borrower].interestIndex = borrowIndex; 77 totalBorrows = vars.totalBorrowsNew; 78 /* We emit a Borrow event */ 79 emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew); 80 } 81 // File contracts/v0.4/math/linkSafeMath.sol 82 /** 83 * @title SafeMath 84 * @dev Math operations with safety checks that throw on error 85 */ 86 library linkSafeMath { 87 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 88 uint256 c = a * b; 89 return c; 90 } 91 function div(uint256 a, uint256 b) internal constant returns (uint256) { 92 // assert(b > 0); // Solidity automatically throws when dividing by 0 93 uint256 c = a / b; 94 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 95 return c; 96 } 97 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 98 return a - b; 99 } 100 function add(uint256 a, uint256 b) internal constant returns (uint256) { 101 uint256 c = a + b; 102 return c; 103 } 104 } | 88+ assert(a == 0 || c / a == b); 97+ assert(b <= a); 101+ assert(c >= a); | 97+ | assert(b <= a); | |||||||||||||||||||||||
77 | 1 // Sources flattened with hardhat v2.1.2 https://hardhat.org 2 // File contracts/v0.4/token/linkERC20Basic.sol 3 pragma solidity ^0.4.11; 4 /** 5 * @title ERC20Basic 6 * @dev Simpler version of ERC20 interface 7 * @dev see https://github.com/ethereum/EIPs/issues/179 8 */ 9 contract linkERC20Basic { 10 uint256 public totalSupply; 11 function balanceOf(address who) constant returns (uint256); 12 function transfer(address to, uint256 value) returns (bool); 13 event Transfer(address indexed from, address indexed to, uint256 value); 14 } 15 // File contracts/v0.4/token/linkERC20.sol 16 /** 17 * @title ERC20 interface 18 * @dev see https://github.com/ethereum/EIPs/issues/20 19 */ 20 contract linkERC20 is linkERC20Basic { 21 function allowance(address owner, address spender) constant returns (uint256); 22 function transferFrom(address from, address to, uint256 value) returns (bool); 23 function approve(address spender, uint256 value) returns (bool); 24 event Approval(address indexed owner, address indexed spender, uint256 value); 25 } 26 // File contracts/v0.4/token/ERC677.sol 27 contract ERC677 is linkERC20 { 28 function transferAndCall(address to, uint value, bytes data) returns (bool success); 29 event Transfer(address indexed from, address indexed to, uint value, bytes data); 30 } 31 // File contracts/v0.4/token/ERC677Receiver.sol 32 contract ERC677Receiver { 33 function onTokenTransfer(address _sender, uint _value, bytes _data); 34 } 35 // File contracts/v0.4/ERC677Token.sol 36 contract ERC677Token is ERC677 { 37 /** 38 * @dev transfer token to a contract address with additional data if the recipient is a contact. 39 * @param _to The address to transfer to. 40 * @param _value The amount to be transferred. 41 * @param _data The extra data to be passed to the receiving contract. 42 */ 43 function transferAndCall(address _to, uint _value, bytes _data) 44 public 45 returns (bool success) 46 { 47 super.transfer(_to, _value); 48 Transfer(msg.sender, _to, _value, _data); 49 if (isContract(_to)) { 50 contractFallback(_to, _value, _data); 51 } 52 return true; 53 } 54 // PRIVATE 55 //bug: this is the buggy fall back that allows reentrancy 56 function contractFallback(address _to, uint _value, bytes _data) 57 private 58 { 59 ERC677Receiver receiver = ERC677Receiver(_to); 60 receiver.onTokenTransfer(msg.sender, _value, _data); 61 } 62 function isContract(address _addr) 63 private 64 returns (bool hasCode) 65 { 66 uint length; 67 assembly { length := extcodesize(_addr) } 68 return length > 0; 69 } 70 } 71 abstract contract CToken { 72 function doTransferOut(address payable to, uint amount) virtual internal; 73 doTransferOut(borrower, borrowAmount); 74 /* We write the previously calculated values into storage */ 75 accountBorrows[borrower].principal = vars.accountBorrowsNew; 76 accountBorrows[borrower].interestIndex = borrowIndex; 77 totalBorrows = vars.totalBorrowsNew; 78 /* We emit a Borrow event */ 79 emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew); 80 } 81 // File contracts/v0.4/math/linkSafeMath.sol 82 /** 83 * @title SafeMath 84 * @dev Math operations with safety checks that throw on error 85 */ 86 library linkSafeMath { 87 function mul(uint256 a, uint256 b) internal constant returns (uint256) { 88 uint256 c = a * b; 89 return c; 90 } 91 function div(uint256 a, uint256 b) internal constant returns (uint256) { 92 // assert(b > 0); // Solidity automatically throws when dividing by 0 93 uint256 c = a / b; 94 // assert(a == b * c + a % b); // There is no case in which this doesn't hold 95 return c; 96 } 97 function sub(uint256 a, uint256 b) internal constant returns (uint256) { 98 return a - b; 99 } 100 function add(uint256 a, uint256 b) internal constant returns (uint256) { 101 uint256 c = a + b; 102 return c; 103 } 104 } | 88+ assert(a == 0 || c / a == b); 97+ assert(b <= a); 101+ assert(c >= a); | 101+ | assert(c >= a); | |||||||||||||||||||||||
78 | 1 // SPDX-License-Identifier: BUSL-1.1 2 pragma solidity 0.7.6; 3 import "@openzeppelin/contracts/math/SafeMath.sol"; 4 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 import "@openzeppelin/contracts/access/Ownable.sol"; 8 import "./interfaces/IVisor.sol"; 9 import "./vVISR.sol"; 10 // @title Rewards Hypervisor 11 // @notice fractionalize balance 12 contract RewardsHypervisor { 13 using SafeERC20 for IERC20; 14 using SafeMath for uint256; 15 address public owner; 16 IERC20 public visr; 17 vVISR public vvisr; 18 modifier onlyOwner { 19 _; 20 } 21 constructor( 22 address _visr, 23 address _vvisr 24 ) { 25 visr = IERC20(_visr); 26 vvisr = vVISR(_vvisr); 27 owner = msg.sender; 28 } 29 function deposit( 30 uint256 visrDeposit, 31 address payable from, 32 address to 33 ) external returns (uint256 shares) { 34 shares = visrDeposit; 35 if (vvisr.totalSupply() != 0) { 36 uint256 visrBalance = visr.balanceOf(address(this)); 37 shares = shares.mul(vvisr.totalSupply()).div(visrBalance); 38 } 39 //this is the buggy line 40 //call the owner function of the attack contract. 41 //As long as the attack contract sets the return value to the contract address 42 // call the delegatedTransferERC20 function of the attack contract. 43 //Here reentrancy is executed 44 if(isContract(from)) { 45 //deposit func is called again 46 IVisor(from).delegatedTransferERC20(address(visr), address(this), visrDeposit); 47 } 48 else { 49 visr.safeTransferFrom(from, address(this), visrDeposit); 50 } 51 vvisr.mint(to, shares); 52 } 53 // @param shares Number of rewards shares to redeem for VISR 54 // @param to Address to which redeemed pool assets are sent 55 // @param from Address from which liquidity tokens are sent 56 // @return rewards Amount of visr redeemed by the submitted liquidity tokens 57 function withdraw( 58 uint256 shares, 59 address to, 60 address payable from 61 ) external returns (uint256 rewards) { 62 rewards = visr.balanceOf(address(this)).mul(shares).div(vvisr.totalSupply()); 63 visr.safeTransfer(to, rewards); 64 vvisr.burn(from, shares); 65 } 66 function snapshot() external onlyOwner { 67 vvisr.snapshot(); 68 } 69 function transferOwnership(address newOwner) external onlyOwner { 70 owner = newOwner; 71 } 72 function transferTokenOwnership(address newOwner) external onlyOwner { 73 vvisr.transferOwnership(newOwner); 74 } 75 function isContract(address _addr) private returns (bool isContract){ 76 uint32 size; 77 assembly { 78 size := extcodesize(_addr) 79 } 80 return (size > 0); 81 } 82 } | 18+ require(msg.sender == owner, "only owner"); 33+ require(visrDeposit > 0, "deposits must be nonzero"); 33+ require(to != address(0) && to != address(this), "to"); 33+ require(from != address(0) && from != address(this), "from"); 44+ require(IVisor(from).owner() == msg.sender); 45+ assert( IVisor(from) != address(this)); 61+ require(shares > 0, "shares"); 61+ require(to != address(0), "to"); 61+ require(from != address(0), "from"); 63+ require(from == msg.sender || IVisor(from).owner() == msg.sender, "Sender must own the tokens"); | 18+ | require(msg.sender == owner, "only owner"); | |||||||||||||||||||||||
79 | 1 // SPDX-License-Identifier: BUSL-1.1 2 pragma solidity 0.7.6; 3 import "@openzeppelin/contracts/math/SafeMath.sol"; 4 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 import "@openzeppelin/contracts/access/Ownable.sol"; 8 import "./interfaces/IVisor.sol"; 9 import "./vVISR.sol"; 10 // @title Rewards Hypervisor 11 // @notice fractionalize balance 12 contract RewardsHypervisor { 13 using SafeERC20 for IERC20; 14 using SafeMath for uint256; 15 address public owner; 16 IERC20 public visr; 17 vVISR public vvisr; 18 modifier onlyOwner { 19 _; 20 } 21 constructor( 22 address _visr, 23 address _vvisr 24 ) { 25 visr = IERC20(_visr); 26 vvisr = vVISR(_vvisr); 27 owner = msg.sender; 28 } 29 function deposit( 30 uint256 visrDeposit, 31 address payable from, 32 address to 33 ) external returns (uint256 shares) { 34 shares = visrDeposit; 35 if (vvisr.totalSupply() != 0) { 36 uint256 visrBalance = visr.balanceOf(address(this)); 37 shares = shares.mul(vvisr.totalSupply()).div(visrBalance); 38 } 39 //this is the buggy line 40 //call the owner function of the attack contract. 41 //As long as the attack contract sets the return value to the contract address 42 // call the delegatedTransferERC20 function of the attack contract. 43 //Here reentrancy is executed 44 if(isContract(from)) { 45 //deposit func is called again 46 IVisor(from).delegatedTransferERC20(address(visr), address(this), visrDeposit); 47 } 48 else { 49 visr.safeTransferFrom(from, address(this), visrDeposit); 50 } 51 vvisr.mint(to, shares); 52 } 53 // @param shares Number of rewards shares to redeem for VISR 54 // @param to Address to which redeemed pool assets are sent 55 // @param from Address from which liquidity tokens are sent 56 // @return rewards Amount of visr redeemed by the submitted liquidity tokens 57 function withdraw( 58 uint256 shares, 59 address to, 60 address payable from 61 ) external returns (uint256 rewards) { 62 rewards = visr.balanceOf(address(this)).mul(shares).div(vvisr.totalSupply()); 63 visr.safeTransfer(to, rewards); 64 vvisr.burn(from, shares); 65 } 66 function snapshot() external onlyOwner { 67 vvisr.snapshot(); 68 } 69 function transferOwnership(address newOwner) external onlyOwner { 70 owner = newOwner; 71 } 72 function transferTokenOwnership(address newOwner) external onlyOwner { 73 vvisr.transferOwnership(newOwner); 74 } 75 function isContract(address _addr) private returns (bool isContract){ 76 uint32 size; 77 assembly { 78 size := extcodesize(_addr) 79 } 80 return (size > 0); 81 } 82 } | 18+ require(msg.sender == owner, "only owner"); 33+ require(visrDeposit > 0, "deposits must be nonzero"); 33+ require(to != address(0) && to != address(this), "to"); 33+ require(from != address(0) && from != address(this), "from"); 44+ require(IVisor(from).owner() == msg.sender); 45+ assert( IVisor(from) != address(this)); 61+ require(shares > 0, "shares"); 61+ require(to != address(0), "to"); 61+ require(from != address(0), "from"); 63+ require(from == msg.sender || IVisor(from).owner() == msg.sender, "Sender must own the tokens"); | 33+ | require(visrDeposit > 0, "deposits must be nonzero"); require(to != address(0) && to != address(this), "to"); require(from != address(0) && from != address(this), "from"); | |||||||||||||||||||||||
80 | 1 // SPDX-License-Identifier: BUSL-1.1 2 pragma solidity 0.7.6; 3 import "@openzeppelin/contracts/math/SafeMath.sol"; 4 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 import "@openzeppelin/contracts/access/Ownable.sol"; 8 import "./interfaces/IVisor.sol"; 9 import "./vVISR.sol"; 10 // @title Rewards Hypervisor 11 // @notice fractionalize balance 12 contract RewardsHypervisor { 13 using SafeERC20 for IERC20; 14 using SafeMath for uint256; 15 address public owner; 16 IERC20 public visr; 17 vVISR public vvisr; 18 modifier onlyOwner { 19 _; 20 } 21 constructor( 22 address _visr, 23 address _vvisr 24 ) { 25 visr = IERC20(_visr); 26 vvisr = vVISR(_vvisr); 27 owner = msg.sender; 28 } 29 function deposit( 30 uint256 visrDeposit, 31 address payable from, 32 address to 33 ) external returns (uint256 shares) { 34 shares = visrDeposit; 35 if (vvisr.totalSupply() != 0) { 36 uint256 visrBalance = visr.balanceOf(address(this)); 37 shares = shares.mul(vvisr.totalSupply()).div(visrBalance); 38 } 39 //this is the buggy line 40 //call the owner function of the attack contract. 41 //As long as the attack contract sets the return value to the contract address 42 // call the delegatedTransferERC20 function of the attack contract. 43 //Here reentrancy is executed 44 if(isContract(from)) { 45 //deposit func is called again 46 IVisor(from).delegatedTransferERC20(address(visr), address(this), visrDeposit); 47 } 48 else { 49 visr.safeTransferFrom(from, address(this), visrDeposit); 50 } 51 vvisr.mint(to, shares); 52 } 53 // @param shares Number of rewards shares to redeem for VISR 54 // @param to Address to which redeemed pool assets are sent 55 // @param from Address from which liquidity tokens are sent 56 // @return rewards Amount of visr redeemed by the submitted liquidity tokens 57 function withdraw( 58 uint256 shares, 59 address to, 60 address payable from 61 ) external returns (uint256 rewards) { 62 rewards = visr.balanceOf(address(this)).mul(shares).div(vvisr.totalSupply()); 63 visr.safeTransfer(to, rewards); 64 vvisr.burn(from, shares); 65 } 66 function snapshot() external onlyOwner { 67 vvisr.snapshot(); 68 } 69 function transferOwnership(address newOwner) external onlyOwner { 70 owner = newOwner; 71 } 72 function transferTokenOwnership(address newOwner) external onlyOwner { 73 vvisr.transferOwnership(newOwner); 74 } 75 function isContract(address _addr) private returns (bool isContract){ 76 uint32 size; 77 assembly { 78 size := extcodesize(_addr) 79 } 80 return (size > 0); 81 } 82 } | 18+ require(msg.sender == owner, "only owner"); 33+ require(visrDeposit > 0, "deposits must be nonzero"); 33+ require(to != address(0) && to != address(this), "to"); 33+ require(from != address(0) && from != address(this), "from"); 44+ require(IVisor(from).owner() == msg.sender); 45+ assert( IVisor(from) != address(this)); 61+ require(shares > 0, "shares"); 61+ require(to != address(0), "to"); 61+ require(from != address(0), "from"); 63+ require(from == msg.sender || IVisor(from).owner() == msg.sender, "Sender must own the tokens"); | 44+ | require(IVisor(from).owner() == msg.sender); | |||||||||||||||||||||||
81 | 1 // SPDX-License-Identifier: BUSL-1.1 2 pragma solidity 0.7.6; 3 import "@openzeppelin/contracts/math/SafeMath.sol"; 4 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 import "@openzeppelin/contracts/access/Ownable.sol"; 8 import "./interfaces/IVisor.sol"; 9 import "./vVISR.sol"; 10 // @title Rewards Hypervisor 11 // @notice fractionalize balance 12 contract RewardsHypervisor { 13 using SafeERC20 for IERC20; 14 using SafeMath for uint256; 15 address public owner; 16 IERC20 public visr; 17 vVISR public vvisr; 18 modifier onlyOwner { 19 _; 20 } 21 constructor( 22 address _visr, 23 address _vvisr 24 ) { 25 visr = IERC20(_visr); 26 vvisr = vVISR(_vvisr); 27 owner = msg.sender; 28 } 29 function deposit( 30 uint256 visrDeposit, 31 address payable from, 32 address to 33 ) external returns (uint256 shares) { 34 shares = visrDeposit; 35 if (vvisr.totalSupply() != 0) { 36 uint256 visrBalance = visr.balanceOf(address(this)); 37 shares = shares.mul(vvisr.totalSupply()).div(visrBalance); 38 } 39 //this is the buggy line 40 //call the owner function of the attack contract. 41 //As long as the attack contract sets the return value to the contract address 42 // call the delegatedTransferERC20 function of the attack contract. 43 //Here reentrancy is executed 44 if(isContract(from)) { 45 //deposit func is called again 46 IVisor(from).delegatedTransferERC20(address(visr), address(this), visrDeposit); 47 } 48 else { 49 visr.safeTransferFrom(from, address(this), visrDeposit); 50 } 51 vvisr.mint(to, shares); 52 } 53 // @param shares Number of rewards shares to redeem for VISR 54 // @param to Address to which redeemed pool assets are sent 55 // @param from Address from which liquidity tokens are sent 56 // @return rewards Amount of visr redeemed by the submitted liquidity tokens 57 function withdraw( 58 uint256 shares, 59 address to, 60 address payable from 61 ) external returns (uint256 rewards) { 62 rewards = visr.balanceOf(address(this)).mul(shares).div(vvisr.totalSupply()); 63 visr.safeTransfer(to, rewards); 64 vvisr.burn(from, shares); 65 } 66 function snapshot() external onlyOwner { 67 vvisr.snapshot(); 68 } 69 function transferOwnership(address newOwner) external onlyOwner { 70 owner = newOwner; 71 } 72 function transferTokenOwnership(address newOwner) external onlyOwner { 73 vvisr.transferOwnership(newOwner); 74 } 75 function isContract(address _addr) private returns (bool isContract){ 76 uint32 size; 77 assembly { 78 size := extcodesize(_addr) 79 } 80 return (size > 0); 81 } 82 } | 18+ require(msg.sender == owner, "only owner"); 33+ require(visrDeposit > 0, "deposits must be nonzero"); 33+ require(to != address(0) && to != address(this), "to"); 33+ require(from != address(0) && from != address(this), "from"); 44+ require(IVisor(from).owner() == msg.sender); 45+ assert( IVisor(from) != address(this)); 61+ require(shares > 0, "shares"); 61+ require(to != address(0), "to"); 61+ require(from != address(0), "from"); 63+ require(from == msg.sender || IVisor(from).owner() == msg.sender, "Sender must own the tokens"); | 45+ | assert( IVisor(from) != address(this)); | |||||||||||||||||||||||
82 | 1 // SPDX-License-Identifier: BUSL-1.1 2 pragma solidity 0.7.6; 3 import "@openzeppelin/contracts/math/SafeMath.sol"; 4 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 import "@openzeppelin/contracts/access/Ownable.sol"; 8 import "./interfaces/IVisor.sol"; 9 import "./vVISR.sol"; 10 // @title Rewards Hypervisor 11 // @notice fractionalize balance 12 contract RewardsHypervisor { 13 using SafeERC20 for IERC20; 14 using SafeMath for uint256; 15 address public owner; 16 IERC20 public visr; 17 vVISR public vvisr; 18 modifier onlyOwner { 19 _; 20 } 21 constructor( 22 address _visr, 23 address _vvisr 24 ) { 25 visr = IERC20(_visr); 26 vvisr = vVISR(_vvisr); 27 owner = msg.sender; 28 } 29 function deposit( 30 uint256 visrDeposit, 31 address payable from, 32 address to 33 ) external returns (uint256 shares) { 34 shares = visrDeposit; 35 if (vvisr.totalSupply() != 0) { 36 uint256 visrBalance = visr.balanceOf(address(this)); 37 shares = shares.mul(vvisr.totalSupply()).div(visrBalance); 38 } 39 //this is the buggy line 40 //call the owner function of the attack contract. 41 //As long as the attack contract sets the return value to the contract address 42 // call the delegatedTransferERC20 function of the attack contract. 43 //Here reentrancy is executed 44 if(isContract(from)) { 45 //deposit func is called again 46 IVisor(from).delegatedTransferERC20(address(visr), address(this), visrDeposit); 47 } 48 else { 49 visr.safeTransferFrom(from, address(this), visrDeposit); 50 } 51 vvisr.mint(to, shares); 52 } 53 // @param shares Number of rewards shares to redeem for VISR 54 // @param to Address to which redeemed pool assets are sent 55 // @param from Address from which liquidity tokens are sent 56 // @return rewards Amount of visr redeemed by the submitted liquidity tokens 57 function withdraw( 58 uint256 shares, 59 address to, 60 address payable from 61 ) external returns (uint256 rewards) { 62 rewards = visr.balanceOf(address(this)).mul(shares).div(vvisr.totalSupply()); 63 visr.safeTransfer(to, rewards); 64 vvisr.burn(from, shares); 65 } 66 function snapshot() external onlyOwner { 67 vvisr.snapshot(); 68 } 69 function transferOwnership(address newOwner) external onlyOwner { 70 owner = newOwner; 71 } 72 function transferTokenOwnership(address newOwner) external onlyOwner { 73 vvisr.transferOwnership(newOwner); 74 } 75 function isContract(address _addr) private returns (bool isContract){ 76 uint32 size; 77 assembly { 78 size := extcodesize(_addr) 79 } 80 return (size > 0); 81 } 82 } | 18+ require(msg.sender == owner, "only owner"); 33+ require(visrDeposit > 0, "deposits must be nonzero"); 33+ require(to != address(0) && to != address(this), "to"); 33+ require(from != address(0) && from != address(this), "from"); 44+ require(IVisor(from).owner() == msg.sender); 45+ assert( IVisor(from) != address(this)); 61+ require(shares > 0, "shares"); 61+ require(to != address(0), "to"); 61+ require(from != address(0), "from"); 63+ require(from == msg.sender || IVisor(from).owner() == msg.sender, "Sender must own the tokens"); | 61+ | require(shares > 0, "shares"); require(from != address(0), "from"); | |||||||||||||||||||||||
83 | 1 // SPDX-License-Identifier: BUSL-1.1 2 pragma solidity 0.7.6; 3 import "@openzeppelin/contracts/math/SafeMath.sol"; 4 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 5 import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; 6 import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol"; 7 import "@openzeppelin/contracts/access/Ownable.sol"; 8 import "./interfaces/IVisor.sol"; 9 import "./vVISR.sol"; 10 // @title Rewards Hypervisor 11 // @notice fractionalize balance 12 contract RewardsHypervisor { 13 using SafeERC20 for IERC20; 14 using SafeMath for uint256; 15 address public owner; 16 IERC20 public visr; 17 vVISR public vvisr; 18 modifier onlyOwner { 19 _; 20 } 21 constructor( 22 address _visr, 23 address _vvisr 24 ) { 25 visr = IERC20(_visr); 26 vvisr = vVISR(_vvisr); 27 owner = msg.sender; 28 } 29 function deposit( 30 uint256 visrDeposit, 31 address payable from, 32 address to 33 ) external returns (uint256 shares) { 34 shares = visrDeposit; 35 if (vvisr.totalSupply() != 0) { 36 uint256 visrBalance = visr.balanceOf(address(this)); 37 shares = shares.mul(vvisr.totalSupply()).div(visrBalance); 38 } 39 //this is the buggy line 40 //call the owner function of the attack contract. 41 //As long as the attack contract sets the return value to the contract address 42 // call the delegatedTransferERC20 function of the attack contract. 43 //Here reentrancy is executed 44 if(isContract(from)) { 45 //deposit func is called again 46 IVisor(from).delegatedTransferERC20(address(visr), address(this), visrDeposit); 47 } 48 else { 49 visr.safeTransferFrom(from, address(this), visrDeposit); 50 } 51 vvisr.mint(to, shares); 52 } 53 // @param shares Number of rewards shares to redeem for VISR 54 // @param to Address to which redeemed pool assets are sent 55 // @param from Address from which liquidity tokens are sent 56 // @return rewards Amount of visr redeemed by the submitted liquidity tokens 57 function withdraw( 58 uint256 shares, 59 address to, 60 address payable from 61 ) external returns (uint256 rewards) { 62 rewards = visr.balanceOf(address(this)).mul(shares).div(vvisr.totalSupply()); 63 visr.safeTransfer(to, rewards); 64 vvisr.burn(from, shares); 65 } 66 function snapshot() external onlyOwner { 67 vvisr.snapshot(); 68 } 69 function transferOwnership(address newOwner) external onlyOwner { 70 owner = newOwner; 71 } 72 function transferTokenOwnership(address newOwner) external onlyOwner { 73 vvisr.transferOwnership(newOwner); 74 } 75 function isContract(address _addr) private returns (bool isContract){ 76 uint32 size; 77 assembly { 78 size := extcodesize(_addr) 79 } 80 return (size > 0); 81 } 82 } | 18+ require(msg.sender == owner, "only owner"); 33+ require(visrDeposit > 0, "deposits must be nonzero"); 33+ require(to != address(0) && to != address(this), "to"); 33+ require(from != address(0) && from != address(this), "from"); 44+ require(IVisor(from).owner() == msg.sender); 45+ assert( IVisor(from) != address(this)); 61+ require(shares > 0, "shares"); 61+ require(to != address(0), "to"); 61+ require(from != address(0), "from"); 63+ require(from == msg.sender || IVisor(from).owner() == msg.sender, "Sender must own the tokens"); | 63+ | require(from == msg.sender || IVisor(from).owner() == msg.sender, "Sender must own the tokens"); | |||||||||||||||||||||||
84 | 1 // SPDX-License-Identifier: GNU-GPL v3.0 or later 2 pragma solidity ^0.8.0; 3 import "@openzeppelin/contracts/access/AccessControl.sol"; 4 import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 5 import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; 6 import "./interfaces/IRevest.sol"; 7 import "./interfaces/IAddressRegistry.sol"; 8 import "./interfaces/ILockManager.sol"; 9 import "./interfaces/ITokenVault.sol"; 10 import "./interfaces/IAddressLock.sol"; 11 import "./utils/RevestAccessControl.sol"; 12 import "./interfaces/IFNFTHandler.sol"; 13 import "./interfaces/IMetadataHandler.sol"; 14 contract FNFTHandler is ERC1155, AccessControl, RevestAccessControl, IFNFTHandler { 15 bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); 16 mapping(uint => uint) public supply; 17 uint public fnftsCreated = 0; 18 /** 19 * @dev Primary constructor to create an instance of NegativeEntropy 20 * Grants ADMIN and MINTER_ROLE to whoever creates the contract 21 */ 22 constructor(address provider) ERC1155("") RevestAccessControl(provider) { 23 _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 24 _setupRole(PAUSER_ROLE, _msgSender()); 25 } 26 /** 27 * @dev See {IERC165-supportsInterface}. 28 */ 29 function supportsInterface(bytes4 interfaceId) public view virtual override (AccessControl, ERC1155) returns (bool) { 30 return super.supportsInterface(interfaceId); 31 } 32 function mint(address account, uint id, uint amount, bytes memory data) external override onlyRevestController { 33 supply[id] += amount; 34 _mint(account, id, amount, data); 35 fnftsCreated += 1; 36 } 37 function mintBatchRec(address[] calldata recipients, uint[] calldata quantities, uint id, uint newSupply, bytes memory data) external override onlyRevestController { 38 supply[id] += newSupply; 39 for(uint i = 0; i < quantities.length; i++) { 40 _mint(recipients[i], id, quantities[i], data); 41 } 42 fnftsCreated += 1; 43 } 44 function mintBatch(address to, uint[] memory ids, uint[] memory amounts, bytes memory data) external override onlyRevestController { 45 _mintBatch(to, ids, amounts, data); 46 } 47 function setURI(string memory newuri) external override onlyRevestController { 48 _setURI(newuri); 49 } 50 function burn(address account, uint id, uint amount) external override onlyRevestController { 51 supply[id] -= amount; 52 _burn(account, id, amount); 53 } 54 function burnBatch(address account, uint[] memory ids, uint[] memory amounts) external override onlyRevestController { 55 _burnBatch(account, ids, amounts); 56 } 57 function getBalance(address account, uint id) external view override returns (uint) { 58 return balanceOf(account, id); 59 } 60 function getSupply(uint fnftId) public view override returns (uint) { 61 return supply[fnftId]; 62 } 63 function getNextId() public view override returns (uint) { 64 return fnftsCreated; 65 } 66 // OVERIDDEN ERC-1155 METHODS 67 function _beforeTokenTransfer( 68 address operator, 69 address from, 70 address to, 71 uint[] memory ids, 72 uint[] memory amounts, 73 bytes memory data 74 ) internal override { 75 super._beforeTokenTransfer(operator, from, to, ids, amounts, data); 76 // Loop because all batch transfers must be checked 77 // Will only execute once on singular transfer 78 if (from != address(0) && to != address(0)) { 79 address vault = addressesProvider.getTokenVault(); 80 bool canTransfer = !ITokenVault(vault).getNontransferable(ids[0]); 81 // Only check if not from minter 82 // And not being burned 83 if(ids.length > 1) { 84 uint iterator = 0; 85 while (canTransfer && iterator < ids.length) { 86 canTransfer = !ITokenVault(vault).getNontransferable(ids[iterator]); 87 iterator += 1; 88 } 89 } 90 } 91 } 92 function uri(uint fnftId) public view override returns (string memory) { 93 return IMetadataHandler(addressesProvider.getMetadataHandler()).getTokenURI(fnftId); 94 } 95 function renderTokenURI( 96 uint tokenId, 97 address owner 98 ) public view returns ( 99 string memory baseRenderURI, 100 string[] memory parameters 101 ) { 102 return IMetadataHandler(addressesProvider.getMetadataHandler()).getRenderTokenURI(tokenId, owner); 103 } 104 } | 32+ require(amount > 0, "Invalid amount"); 32+ require(supply[id] == 0, "Repeated mint for the same FNFT"); 89+ require(canTransfer, "E046"); | 32+ | require(amount > 0, "Invalid amount"); require(supply[id] == 0, "Repeated mint for the same FNFT"); | |||||||||||||||||||||||
85 | 1 // SPDX-License-Identifier: GNU-GPL v3.0 or later 2 pragma solidity ^0.8.0; 3 import "@openzeppelin/contracts/access/AccessControl.sol"; 4 import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; 5 import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; 6 import "./interfaces/IRevest.sol"; 7 import "./interfaces/IAddressRegistry.sol"; 8 import "./interfaces/ILockManager.sol"; 9 import "./interfaces/ITokenVault.sol"; 10 import "./interfaces/IAddressLock.sol"; 11 import "./utils/RevestAccessControl.sol"; 12 import "./interfaces/IFNFTHandler.sol"; 13 import "./interfaces/IMetadataHandler.sol"; 14 contract FNFTHandler is ERC1155, AccessControl, RevestAccessControl, IFNFTHandler { 15 bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE"); 16 mapping(uint => uint) public supply; 17 uint public fnftsCreated = 0; 18 /** 19 * @dev Primary constructor to create an instance of NegativeEntropy 20 * Grants ADMIN and MINTER_ROLE to whoever creates the contract 21 */ 22 constructor(address provider) ERC1155("") RevestAccessControl(provider) { 23 _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); 24 _setupRole(PAUSER_ROLE, _msgSender()); 25 } 26 /** 27 * @dev See {IERC165-supportsInterface}. 28 */ 29 function supportsInterface(bytes4 interfaceId) public view virtual override (AccessControl, ERC1155) returns (bool) { 30 return super.supportsInterface(interfaceId); 31 } 32 function mint(address account, uint id, uint amount, bytes memory data) external override onlyRevestController { 33 supply[id] += amount; 34 _mint(account, id, amount, data); 35 fnftsCreated += 1; 36 } 37 function mintBatchRec(address[] calldata recipients, uint[] calldata quantities, uint id, uint newSupply, bytes memory data) external override onlyRevestController { 38 supply[id] += newSupply; 39 for(uint i = 0; i < quantities.length; i++) { 40 _mint(recipients[i], id, quantities[i], data); 41 } 42 fnftsCreated += 1; 43 } 44 function mintBatch(address to, uint[] memory ids, uint[] memory amounts, bytes memory data) external override onlyRevestController { 45 _mintBatch(to, ids, amounts, data); 46 } 47 function setURI(string memory newuri) external override onlyRevestController { 48 _setURI(newuri); 49 } 50 function burn(address account, uint id, uint amount) external override onlyRevestController { 51 supply[id] -= amount; 52 _burn(account, id, amount); 53 } 54 function burnBatch(address account, uint[] memory ids, uint[] memory amounts) external override onlyRevestController { 55 _burnBatch(account, ids, amounts); 56 } 57 function getBalance(address account, uint id) external view override returns (uint) { 58 return balanceOf(account, id); 59 } 60 function getSupply(uint fnftId) public view override returns (uint) { 61 return supply[fnftId]; 62 } 63 function getNextId() public view override returns (uint) { 64 return fnftsCreated; 65 } 66 // OVERIDDEN ERC-1155 METHODS 67 function _beforeTokenTransfer( 68 address operator, 69 address from, 70 address to, 71 uint[] memory ids, 72 uint[] memory amounts, 73 bytes memory data 74 ) internal override { 75 super._beforeTokenTransfer(operator, from, to, ids, amounts, data); 76 // Loop because all batch transfers must be checked 77 // Will only execute once on singular transfer 78 if (from != address(0) && to != address(0)) { 79 address vault = addressesProvider.getTokenVault(); 80 bool canTransfer = !ITokenVault(vault).getNontransferable(ids[0]); 81 // Only check if not from minter 82 // And not being burned 83 if(ids.length > 1) { 84 uint iterator = 0; 85 while (canTransfer && iterator < ids.length) { 86 canTransfer = !ITokenVault(vault).getNontransferable(ids[iterator]); 87 iterator += 1; 88 } 89 } 90 } 91 } 92 function uri(uint fnftId) public view override returns (string memory) { 93 return IMetadataHandler(addressesProvider.getMetadataHandler()).getTokenURI(fnftId); 94 } 95 function renderTokenURI( 96 uint tokenId, 97 address owner 98 ) public view returns ( 99 string memory baseRenderURI, 100 string[] memory parameters 101 ) { 102 return IMetadataHandler(addressesProvider.getMetadataHandler()).getRenderTokenURI(tokenId, owner); 103 } 104 } | 32+ require(amount > 0, "Invalid amount"); 32+ require(supply[id] == 0, "Repeated mint for the same FNFT"); 89+ require(canTransfer, "E046"); | 89+ | require(canTransfer, "E046"); | |||||||||||||||||||||||
86 | 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.7; 3 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 import { LibAsset } from "../Libraries/LibAsset.sol"; 5 import { ILiFi } from "../Interfaces/ILiFi.sol"; 6 import { LibSwap } from "../Libraries/LibSwap.sol"; 7 import { ICBridge } from "../Interfaces/ICBridge.sol"; 8 import { LibDiamond } from "../Libraries/LibDiamond.sol"; 9 /** 10 * @title CBridge Facet 11 * @author Li.Finance (https://li.finance) 12 * @notice Provides functionality for bridging through CBridge 13 */ 14 contract CBridgeFacet is ILiFi { 15 /* ========== Storage ========== */ 16 bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.cbridge2"); 17 invokeSwap bool; 18 struct Storage { 19 address cBridge; 20 uint64 cBridgeChainId; 21 } 22 /* ========== Types ========== */ 23 struct CBridgeData { 24 address receiver; 25 address token; 26 uint256 amount; 27 uint64 dstChainId; 28 uint64 nonce; 29 uint32 maxSlippage; 30 } 31 /* ========== Init ========== */ 32 /** 33 * @notice Initializes local variables for the CBridge facet 34 * @param _cBridge address of the canonical CBridge router contract 35 * @param _chainId chainId of this deployed contract 36 */ 37 function initCbridge(address _cBridge, uint64 _chainId) external { 38 Storage storage s = getStorage(); 39 LibDiamond.enforceIsContractOwner(); 40 s.cBridge = _cBridge; 41 s.cBridgeChainId = _chainId; 42 emit Inited(s.cBridge, s.cBridgeChainId); 43 } 44 /* ========== Public Bridge Functions ========== */ 45 /** 46 * @notice Bridges tokens via CBridge 47 * @param _lifiData data used purely for tracking and analytics 48 * @param _cBridgeData data specific to CBridge 49 */ 50 function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData calldata _cBridgeData) public payable { 51 if (_cBridgeData.token != address(0)) { 52 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 53 LibAsset.transferFromERC20(_cBridgeData.token, msg.sender, address(this), _cBridgeData.amount); 54 require( 55 LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance == _cBridgeData.amount, 56 "ERR_INVALID_AMOUNT" 57 ); 58 } else { 59 _; 60 } 61 _startBridge(_cBridgeData); 62 emit LiFiTransferStarted( 63 _lifiData.transactionId, 64 _lifiData.integrator, 65 _lifiData.referrer, 66 _lifiData.sendingAssetId, 67 _lifiData.receivingAssetId, 68 _lifiData.receiver, 69 _lifiData.amount, 70 _lifiData.destinationChainId, 71 block.timestamp 72 ); 73 } 74 /** 75 * @notice Performs a swap before bridging via CBridge 76 * @param _lifiData data used purely for tracking and analytics 77 * @param _swapData an array of swap related data for performing swaps before bridging 78 * @param _cBridgeData data specific to CBridge 79 */ 80 function swapAndStartBridgeTokensViaCBridge( 81 LiFiData memory _lifiData, 82 LibSwap.SwapData[] calldata _swapData, 83 CBridgeData memory _cBridgeData 84 ) public payable { 85 if (_cBridgeData.token != address(0)) { 86 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 87 // Swap 88 for (uint8 i; i < _swapData.length; i++) { 89 invokeSwap = true; 90 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 91 } 92 uint256 _postSwapBalance = LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance; 93 _cBridgeData.amount = _postSwapBalance; 94 } else { 95 uint256 _fromBalance = address(this).balance; 96 // Swap 97 for (uint8 i; i < _swapData.length; i++) { 98 invokeSwap = true; 99 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 100 } 101 uint256 _postSwapBalance = address(this).balance - _fromBalance; 102 _cBridgeData.amount = _postSwapBalance; 103 } 104 _startBridge(_cBridgeData); 105 emit LiFiTransferStarted( 106 _lifiData.transactionId, 107 _lifiData.integrator, 108 _lifiData.referrer, 109 _lifiData.sendingAssetId, 110 _lifiData.receivingAssetId, 111 _lifiData.receiver, 112 _lifiData.amount, 113 _lifiData.destinationChainId, 114 block.timestamp 115 ); 116 } 117 /* ========== Internal Functions ========== */ 118 /* 119 * @dev Conatains the business logic for the bridge via CBridge 120 * @param _cBridgeData data specific to CBridge 121 */ 122 function _startBridge(CBridgeData memory _cBridgeData) internal { 123 Storage storage s = getStorage(); 124 address bridge = _bridge(); 125 // Do CBridge stuff 126 if (LibAsset.isNativeAsset(_cBridgeData.token)) { 127 ICBridge(bridge).sendNative( 128 _cBridgeData.receiver, 129 _cBridgeData.amount, 130 _cBridgeData.dstChainId, 131 _cBridgeData.nonce, 132 _cBridgeData.maxSlippage 133 ); 134 } else { 135 // Give CBridge approval to bridge tokens 136 LibAsset.approveERC20(IERC20(_cBridgeData.token), bridge, _cBridgeData.amount); 137 // solhint-disable check-send-result 138 ICBridge(bridge).send( 139 _cBridgeData.receiver, 140 _cBridgeData.token, 141 _cBridgeData.amount, 142 _cBridgeData.dstChainId, 143 _cBridgeData.nonce, 144 _cBridgeData.maxSlippage 145 ); 146 } 147 } 148 /* 149 * @dev Public view function for the CBridge router address 150 * @returns the router address 151 */ 152 function _bridge() internal view returns (address) { 153 Storage storage s = getStorage(); 154 return s.cBridge; 155 } 156 /** 157 * @dev fetch local storage 158 */ 159 function getStorage() internal pure returns (Storage storage s) { 160 bytes32 namespace = NAMESPACE; 161 // solhint-disable-next-line no-inline-assembly 162 assembly { 163 s.slot := namespace 164 } 165 } 166 } 167 // SPDX-License-Identifier: MIT 168 pragma solidity ^0.8.7; 169 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 170 import { LibAsset } from "./LibAsset.sol"; 171 import { LibUtil } from "./LibUtil.sol"; 172 library LibSwap { 173 uint256 private constant MAX_INT = 2**256 - 1; 174 struct SwapData { 175 address callTo; 176 address approveTo; 177 address sendingAssetId; 178 address receivingAssetId; 179 uint256 fromAmount; 180 bytes callData; 181 } 182 event AssetSwapped( 183 bytes32 transactionId, 184 address dex, 185 address fromAssetId, 186 address toAssetId, 187 uint256 fromAmount, 188 uint256 toAmount, 189 uint256 timestamp 190 ); 191 function swap(bytes32 transactionId, SwapData calldata _swapData, bool invokeSwap) internal { 192 uint256 fromAmount = _swapData.fromAmount; 193 uint256 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId); 194 address fromAssetId = _swapData.sendingAssetId; 195 if (!LibAsset.isNativeAsset(fromAssetId) && LibAsset.getOwnBalance(fromAssetId) < fromAmount) { 196 LibAsset.transferFromERC20(_swapData.sendingAssetId, msg.sender, address(this), fromAmount); 197 } 198 if (!LibAsset.isNativeAsset(fromAssetId)) { 199 LibAsset.approveERC20(IERC20(fromAssetId), _swapData.approveTo, fromAmount); 200 } 201 // solhint-disable-next-line avoid-low-level-calls 202 (bool success, bytes memory res) = _swapData.callTo.call{ value: msg.value }(_swapData.callData); 203 if (!success) { 204 string memory reason = LibUtil.getRevertMsg(res); 205 revert(reason); 206 } 207 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId) - toAmount; 208 emit AssetSwapped( 209 transactionId, 210 _swapData.callTo, 211 _swapData.sendingAssetId, 212 _swapData.receivingAssetId, 213 fromAmount, 214 toAmount, 215 block.timestamp 216 ); 217 } 218 } | 58+ require(msg.value >= _cBridgeData.amount, "ERR_INVALID_AMOUNT"); 92+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 101+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 125+ require(s.cBridgeChainId != _cBridgeData.dstChainId, "Cannot bridge to the same network."); 191+ assert(!invokeSwap); | 58+ | require(msg.value >= _cBridgeData.amount, "ERR_INVALID_AMOUNT"); | |||||||||||||||||||||||
87 | 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.7; 3 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 import { LibAsset } from "../Libraries/LibAsset.sol"; 5 import { ILiFi } from "../Interfaces/ILiFi.sol"; 6 import { LibSwap } from "../Libraries/LibSwap.sol"; 7 import { ICBridge } from "../Interfaces/ICBridge.sol"; 8 import { LibDiamond } from "../Libraries/LibDiamond.sol"; 9 /** 10 * @title CBridge Facet 11 * @author Li.Finance (https://li.finance) 12 * @notice Provides functionality for bridging through CBridge 13 */ 14 contract CBridgeFacet is ILiFi { 15 /* ========== Storage ========== */ 16 bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.cbridge2"); 17 invokeSwap bool; 18 struct Storage { 19 address cBridge; 20 uint64 cBridgeChainId; 21 } 22 /* ========== Types ========== */ 23 struct CBridgeData { 24 address receiver; 25 address token; 26 uint256 amount; 27 uint64 dstChainId; 28 uint64 nonce; 29 uint32 maxSlippage; 30 } 31 /* ========== Init ========== */ 32 /** 33 * @notice Initializes local variables for the CBridge facet 34 * @param _cBridge address of the canonical CBridge router contract 35 * @param _chainId chainId of this deployed contract 36 */ 37 function initCbridge(address _cBridge, uint64 _chainId) external { 38 Storage storage s = getStorage(); 39 LibDiamond.enforceIsContractOwner(); 40 s.cBridge = _cBridge; 41 s.cBridgeChainId = _chainId; 42 emit Inited(s.cBridge, s.cBridgeChainId); 43 } 44 /* ========== Public Bridge Functions ========== */ 45 /** 46 * @notice Bridges tokens via CBridge 47 * @param _lifiData data used purely for tracking and analytics 48 * @param _cBridgeData data specific to CBridge 49 */ 50 function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData calldata _cBridgeData) public payable { 51 if (_cBridgeData.token != address(0)) { 52 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 53 LibAsset.transferFromERC20(_cBridgeData.token, msg.sender, address(this), _cBridgeData.amount); 54 require( 55 LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance == _cBridgeData.amount, 56 "ERR_INVALID_AMOUNT" 57 ); 58 } else { 59 _; 60 } 61 _startBridge(_cBridgeData); 62 emit LiFiTransferStarted( 63 _lifiData.transactionId, 64 _lifiData.integrator, 65 _lifiData.referrer, 66 _lifiData.sendingAssetId, 67 _lifiData.receivingAssetId, 68 _lifiData.receiver, 69 _lifiData.amount, 70 _lifiData.destinationChainId, 71 block.timestamp 72 ); 73 } 74 /** 75 * @notice Performs a swap before bridging via CBridge 76 * @param _lifiData data used purely for tracking and analytics 77 * @param _swapData an array of swap related data for performing swaps before bridging 78 * @param _cBridgeData data specific to CBridge 79 */ 80 function swapAndStartBridgeTokensViaCBridge( 81 LiFiData memory _lifiData, 82 LibSwap.SwapData[] calldata _swapData, 83 CBridgeData memory _cBridgeData 84 ) public payable { 85 if (_cBridgeData.token != address(0)) { 86 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 87 // Swap 88 for (uint8 i; i < _swapData.length; i++) { 89 invokeSwap = true; 90 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 91 } 92 uint256 _postSwapBalance = LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance; 93 _cBridgeData.amount = _postSwapBalance; 94 } else { 95 uint256 _fromBalance = address(this).balance; 96 // Swap 97 for (uint8 i; i < _swapData.length; i++) { 98 invokeSwap = true; 99 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 100 } 101 uint256 _postSwapBalance = address(this).balance - _fromBalance; 102 _cBridgeData.amount = _postSwapBalance; 103 } 104 _startBridge(_cBridgeData); 105 emit LiFiTransferStarted( 106 _lifiData.transactionId, 107 _lifiData.integrator, 108 _lifiData.referrer, 109 _lifiData.sendingAssetId, 110 _lifiData.receivingAssetId, 111 _lifiData.receiver, 112 _lifiData.amount, 113 _lifiData.destinationChainId, 114 block.timestamp 115 ); 116 } 117 /* ========== Internal Functions ========== */ 118 /* 119 * @dev Conatains the business logic for the bridge via CBridge 120 * @param _cBridgeData data specific to CBridge 121 */ 122 function _startBridge(CBridgeData memory _cBridgeData) internal { 123 Storage storage s = getStorage(); 124 address bridge = _bridge(); 125 // Do CBridge stuff 126 if (LibAsset.isNativeAsset(_cBridgeData.token)) { 127 ICBridge(bridge).sendNative( 128 _cBridgeData.receiver, 129 _cBridgeData.amount, 130 _cBridgeData.dstChainId, 131 _cBridgeData.nonce, 132 _cBridgeData.maxSlippage 133 ); 134 } else { 135 // Give CBridge approval to bridge tokens 136 LibAsset.approveERC20(IERC20(_cBridgeData.token), bridge, _cBridgeData.amount); 137 // solhint-disable check-send-result 138 ICBridge(bridge).send( 139 _cBridgeData.receiver, 140 _cBridgeData.token, 141 _cBridgeData.amount, 142 _cBridgeData.dstChainId, 143 _cBridgeData.nonce, 144 _cBridgeData.maxSlippage 145 ); 146 } 147 } 148 /* 149 * @dev Public view function for the CBridge router address 150 * @returns the router address 151 */ 152 function _bridge() internal view returns (address) { 153 Storage storage s = getStorage(); 154 return s.cBridge; 155 } 156 /** 157 * @dev fetch local storage 158 */ 159 function getStorage() internal pure returns (Storage storage s) { 160 bytes32 namespace = NAMESPACE; 161 // solhint-disable-next-line no-inline-assembly 162 assembly { 163 s.slot := namespace 164 } 165 } 166 } 167 // SPDX-License-Identifier: MIT 168 pragma solidity ^0.8.7; 169 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 170 import { LibAsset } from "./LibAsset.sol"; 171 import { LibUtil } from "./LibUtil.sol"; 172 library LibSwap { 173 uint256 private constant MAX_INT = 2**256 - 1; 174 struct SwapData { 175 address callTo; 176 address approveTo; 177 address sendingAssetId; 178 address receivingAssetId; 179 uint256 fromAmount; 180 bytes callData; 181 } 182 event AssetSwapped( 183 bytes32 transactionId, 184 address dex, 185 address fromAssetId, 186 address toAssetId, 187 uint256 fromAmount, 188 uint256 toAmount, 189 uint256 timestamp 190 ); 191 function swap(bytes32 transactionId, SwapData calldata _swapData, bool invokeSwap) internal { 192 uint256 fromAmount = _swapData.fromAmount; 193 uint256 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId); 194 address fromAssetId = _swapData.sendingAssetId; 195 if (!LibAsset.isNativeAsset(fromAssetId) && LibAsset.getOwnBalance(fromAssetId) < fromAmount) { 196 LibAsset.transferFromERC20(_swapData.sendingAssetId, msg.sender, address(this), fromAmount); 197 } 198 if (!LibAsset.isNativeAsset(fromAssetId)) { 199 LibAsset.approveERC20(IERC20(fromAssetId), _swapData.approveTo, fromAmount); 200 } 201 // solhint-disable-next-line avoid-low-level-calls 202 (bool success, bytes memory res) = _swapData.callTo.call{ value: msg.value }(_swapData.callData); 203 if (!success) { 204 string memory reason = LibUtil.getRevertMsg(res); 205 revert(reason); 206 } 207 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId) - toAmount; 208 emit AssetSwapped( 209 transactionId, 210 _swapData.callTo, 211 _swapData.sendingAssetId, 212 _swapData.receivingAssetId, 213 fromAmount, 214 toAmount, 215 block.timestamp 216 ); 217 } 218 } | 58+ require(msg.value >= _cBridgeData.amount, "ERR_INVALID_AMOUNT"); 92+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 101+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 125+ require(s.cBridgeChainId != _cBridgeData.dstChainId, "Cannot bridge to the same network."); 191+ assert(!invokeSwap); | 92+ | require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); | |||||||||||||||||||||||
88 | 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.7; 3 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 import { LibAsset } from "../Libraries/LibAsset.sol"; 5 import { ILiFi } from "../Interfaces/ILiFi.sol"; 6 import { LibSwap } from "../Libraries/LibSwap.sol"; 7 import { ICBridge } from "../Interfaces/ICBridge.sol"; 8 import { LibDiamond } from "../Libraries/LibDiamond.sol"; 9 /** 10 * @title CBridge Facet 11 * @author Li.Finance (https://li.finance) 12 * @notice Provides functionality for bridging through CBridge 13 */ 14 contract CBridgeFacet is ILiFi { 15 /* ========== Storage ========== */ 16 bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.cbridge2"); 17 invokeSwap bool; 18 struct Storage { 19 address cBridge; 20 uint64 cBridgeChainId; 21 } 22 /* ========== Types ========== */ 23 struct CBridgeData { 24 address receiver; 25 address token; 26 uint256 amount; 27 uint64 dstChainId; 28 uint64 nonce; 29 uint32 maxSlippage; 30 } 31 /* ========== Init ========== */ 32 /** 33 * @notice Initializes local variables for the CBridge facet 34 * @param _cBridge address of the canonical CBridge router contract 35 * @param _chainId chainId of this deployed contract 36 */ 37 function initCbridge(address _cBridge, uint64 _chainId) external { 38 Storage storage s = getStorage(); 39 LibDiamond.enforceIsContractOwner(); 40 s.cBridge = _cBridge; 41 s.cBridgeChainId = _chainId; 42 emit Inited(s.cBridge, s.cBridgeChainId); 43 } 44 /* ========== Public Bridge Functions ========== */ 45 /** 46 * @notice Bridges tokens via CBridge 47 * @param _lifiData data used purely for tracking and analytics 48 * @param _cBridgeData data specific to CBridge 49 */ 50 function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData calldata _cBridgeData) public payable { 51 if (_cBridgeData.token != address(0)) { 52 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 53 LibAsset.transferFromERC20(_cBridgeData.token, msg.sender, address(this), _cBridgeData.amount); 54 require( 55 LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance == _cBridgeData.amount, 56 "ERR_INVALID_AMOUNT" 57 ); 58 } else { 59 _; 60 } 61 _startBridge(_cBridgeData); 62 emit LiFiTransferStarted( 63 _lifiData.transactionId, 64 _lifiData.integrator, 65 _lifiData.referrer, 66 _lifiData.sendingAssetId, 67 _lifiData.receivingAssetId, 68 _lifiData.receiver, 69 _lifiData.amount, 70 _lifiData.destinationChainId, 71 block.timestamp 72 ); 73 } 74 /** 75 * @notice Performs a swap before bridging via CBridge 76 * @param _lifiData data used purely for tracking and analytics 77 * @param _swapData an array of swap related data for performing swaps before bridging 78 * @param _cBridgeData data specific to CBridge 79 */ 80 function swapAndStartBridgeTokensViaCBridge( 81 LiFiData memory _lifiData, 82 LibSwap.SwapData[] calldata _swapData, 83 CBridgeData memory _cBridgeData 84 ) public payable { 85 if (_cBridgeData.token != address(0)) { 86 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 87 // Swap 88 for (uint8 i; i < _swapData.length; i++) { 89 invokeSwap = true; 90 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 91 } 92 uint256 _postSwapBalance = LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance; 93 _cBridgeData.amount = _postSwapBalance; 94 } else { 95 uint256 _fromBalance = address(this).balance; 96 // Swap 97 for (uint8 i; i < _swapData.length; i++) { 98 invokeSwap = true; 99 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 100 } 101 uint256 _postSwapBalance = address(this).balance - _fromBalance; 102 _cBridgeData.amount = _postSwapBalance; 103 } 104 _startBridge(_cBridgeData); 105 emit LiFiTransferStarted( 106 _lifiData.transactionId, 107 _lifiData.integrator, 108 _lifiData.referrer, 109 _lifiData.sendingAssetId, 110 _lifiData.receivingAssetId, 111 _lifiData.receiver, 112 _lifiData.amount, 113 _lifiData.destinationChainId, 114 block.timestamp 115 ); 116 } 117 /* ========== Internal Functions ========== */ 118 /* 119 * @dev Conatains the business logic for the bridge via CBridge 120 * @param _cBridgeData data specific to CBridge 121 */ 122 function _startBridge(CBridgeData memory _cBridgeData) internal { 123 Storage storage s = getStorage(); 124 address bridge = _bridge(); 125 // Do CBridge stuff 126 if (LibAsset.isNativeAsset(_cBridgeData.token)) { 127 ICBridge(bridge).sendNative( 128 _cBridgeData.receiver, 129 _cBridgeData.amount, 130 _cBridgeData.dstChainId, 131 _cBridgeData.nonce, 132 _cBridgeData.maxSlippage 133 ); 134 } else { 135 // Give CBridge approval to bridge tokens 136 LibAsset.approveERC20(IERC20(_cBridgeData.token), bridge, _cBridgeData.amount); 137 // solhint-disable check-send-result 138 ICBridge(bridge).send( 139 _cBridgeData.receiver, 140 _cBridgeData.token, 141 _cBridgeData.amount, 142 _cBridgeData.dstChainId, 143 _cBridgeData.nonce, 144 _cBridgeData.maxSlippage 145 ); 146 } 147 } 148 /* 149 * @dev Public view function for the CBridge router address 150 * @returns the router address 151 */ 152 function _bridge() internal view returns (address) { 153 Storage storage s = getStorage(); 154 return s.cBridge; 155 } 156 /** 157 * @dev fetch local storage 158 */ 159 function getStorage() internal pure returns (Storage storage s) { 160 bytes32 namespace = NAMESPACE; 161 // solhint-disable-next-line no-inline-assembly 162 assembly { 163 s.slot := namespace 164 } 165 } 166 } 167 // SPDX-License-Identifier: MIT 168 pragma solidity ^0.8.7; 169 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 170 import { LibAsset } from "./LibAsset.sol"; 171 import { LibUtil } from "./LibUtil.sol"; 172 library LibSwap { 173 uint256 private constant MAX_INT = 2**256 - 1; 174 struct SwapData { 175 address callTo; 176 address approveTo; 177 address sendingAssetId; 178 address receivingAssetId; 179 uint256 fromAmount; 180 bytes callData; 181 } 182 event AssetSwapped( 183 bytes32 transactionId, 184 address dex, 185 address fromAssetId, 186 address toAssetId, 187 uint256 fromAmount, 188 uint256 toAmount, 189 uint256 timestamp 190 ); 191 function swap(bytes32 transactionId, SwapData calldata _swapData, bool invokeSwap) internal { 192 uint256 fromAmount = _swapData.fromAmount; 193 uint256 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId); 194 address fromAssetId = _swapData.sendingAssetId; 195 if (!LibAsset.isNativeAsset(fromAssetId) && LibAsset.getOwnBalance(fromAssetId) < fromAmount) { 196 LibAsset.transferFromERC20(_swapData.sendingAssetId, msg.sender, address(this), fromAmount); 197 } 198 if (!LibAsset.isNativeAsset(fromAssetId)) { 199 LibAsset.approveERC20(IERC20(fromAssetId), _swapData.approveTo, fromAmount); 200 } 201 // solhint-disable-next-line avoid-low-level-calls 202 (bool success, bytes memory res) = _swapData.callTo.call{ value: msg.value }(_swapData.callData); 203 if (!success) { 204 string memory reason = LibUtil.getRevertMsg(res); 205 revert(reason); 206 } 207 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId) - toAmount; 208 emit AssetSwapped( 209 transactionId, 210 _swapData.callTo, 211 _swapData.sendingAssetId, 212 _swapData.receivingAssetId, 213 fromAmount, 214 toAmount, 215 block.timestamp 216 ); 217 } 218 } | 58+ require(msg.value >= _cBridgeData.amount, "ERR_INVALID_AMOUNT"); 92+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 101+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 125+ require(s.cBridgeChainId != _cBridgeData.dstChainId, "Cannot bridge to the same network."); 191+ assert(!invokeSwap); | 101+ | require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); | |||||||||||||||||||||||
89 | 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.7; 3 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 import { LibAsset } from "../Libraries/LibAsset.sol"; 5 import { ILiFi } from "../Interfaces/ILiFi.sol"; 6 import { LibSwap } from "../Libraries/LibSwap.sol"; 7 import { ICBridge } from "../Interfaces/ICBridge.sol"; 8 import { LibDiamond } from "../Libraries/LibDiamond.sol"; 9 /** 10 * @title CBridge Facet 11 * @author Li.Finance (https://li.finance) 12 * @notice Provides functionality for bridging through CBridge 13 */ 14 contract CBridgeFacet is ILiFi { 15 /* ========== Storage ========== */ 16 bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.cbridge2"); 17 invokeSwap bool; 18 struct Storage { 19 address cBridge; 20 uint64 cBridgeChainId; 21 } 22 /* ========== Types ========== */ 23 struct CBridgeData { 24 address receiver; 25 address token; 26 uint256 amount; 27 uint64 dstChainId; 28 uint64 nonce; 29 uint32 maxSlippage; 30 } 31 /* ========== Init ========== */ 32 /** 33 * @notice Initializes local variables for the CBridge facet 34 * @param _cBridge address of the canonical CBridge router contract 35 * @param _chainId chainId of this deployed contract 36 */ 37 function initCbridge(address _cBridge, uint64 _chainId) external { 38 Storage storage s = getStorage(); 39 LibDiamond.enforceIsContractOwner(); 40 s.cBridge = _cBridge; 41 s.cBridgeChainId = _chainId; 42 emit Inited(s.cBridge, s.cBridgeChainId); 43 } 44 /* ========== Public Bridge Functions ========== */ 45 /** 46 * @notice Bridges tokens via CBridge 47 * @param _lifiData data used purely for tracking and analytics 48 * @param _cBridgeData data specific to CBridge 49 */ 50 function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData calldata _cBridgeData) public payable { 51 if (_cBridgeData.token != address(0)) { 52 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 53 LibAsset.transferFromERC20(_cBridgeData.token, msg.sender, address(this), _cBridgeData.amount); 54 require( 55 LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance == _cBridgeData.amount, 56 "ERR_INVALID_AMOUNT" 57 ); 58 } else { 59 _; 60 } 61 _startBridge(_cBridgeData); 62 emit LiFiTransferStarted( 63 _lifiData.transactionId, 64 _lifiData.integrator, 65 _lifiData.referrer, 66 _lifiData.sendingAssetId, 67 _lifiData.receivingAssetId, 68 _lifiData.receiver, 69 _lifiData.amount, 70 _lifiData.destinationChainId, 71 block.timestamp 72 ); 73 } 74 /** 75 * @notice Performs a swap before bridging via CBridge 76 * @param _lifiData data used purely for tracking and analytics 77 * @param _swapData an array of swap related data for performing swaps before bridging 78 * @param _cBridgeData data specific to CBridge 79 */ 80 function swapAndStartBridgeTokensViaCBridge( 81 LiFiData memory _lifiData, 82 LibSwap.SwapData[] calldata _swapData, 83 CBridgeData memory _cBridgeData 84 ) public payable { 85 if (_cBridgeData.token != address(0)) { 86 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 87 // Swap 88 for (uint8 i; i < _swapData.length; i++) { 89 invokeSwap = true; 90 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 91 } 92 uint256 _postSwapBalance = LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance; 93 _cBridgeData.amount = _postSwapBalance; 94 } else { 95 uint256 _fromBalance = address(this).balance; 96 // Swap 97 for (uint8 i; i < _swapData.length; i++) { 98 invokeSwap = true; 99 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 100 } 101 uint256 _postSwapBalance = address(this).balance - _fromBalance; 102 _cBridgeData.amount = _postSwapBalance; 103 } 104 _startBridge(_cBridgeData); 105 emit LiFiTransferStarted( 106 _lifiData.transactionId, 107 _lifiData.integrator, 108 _lifiData.referrer, 109 _lifiData.sendingAssetId, 110 _lifiData.receivingAssetId, 111 _lifiData.receiver, 112 _lifiData.amount, 113 _lifiData.destinationChainId, 114 block.timestamp 115 ); 116 } 117 /* ========== Internal Functions ========== */ 118 /* 119 * @dev Conatains the business logic for the bridge via CBridge 120 * @param _cBridgeData data specific to CBridge 121 */ 122 function _startBridge(CBridgeData memory _cBridgeData) internal { 123 Storage storage s = getStorage(); 124 address bridge = _bridge(); 125 // Do CBridge stuff 126 if (LibAsset.isNativeAsset(_cBridgeData.token)) { 127 ICBridge(bridge).sendNative( 128 _cBridgeData.receiver, 129 _cBridgeData.amount, 130 _cBridgeData.dstChainId, 131 _cBridgeData.nonce, 132 _cBridgeData.maxSlippage 133 ); 134 } else { 135 // Give CBridge approval to bridge tokens 136 LibAsset.approveERC20(IERC20(_cBridgeData.token), bridge, _cBridgeData.amount); 137 // solhint-disable check-send-result 138 ICBridge(bridge).send( 139 _cBridgeData.receiver, 140 _cBridgeData.token, 141 _cBridgeData.amount, 142 _cBridgeData.dstChainId, 143 _cBridgeData.nonce, 144 _cBridgeData.maxSlippage 145 ); 146 } 147 } 148 /* 149 * @dev Public view function for the CBridge router address 150 * @returns the router address 151 */ 152 function _bridge() internal view returns (address) { 153 Storage storage s = getStorage(); 154 return s.cBridge; 155 } 156 /** 157 * @dev fetch local storage 158 */ 159 function getStorage() internal pure returns (Storage storage s) { 160 bytes32 namespace = NAMESPACE; 161 // solhint-disable-next-line no-inline-assembly 162 assembly { 163 s.slot := namespace 164 } 165 } 166 } 167 // SPDX-License-Identifier: MIT 168 pragma solidity ^0.8.7; 169 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 170 import { LibAsset } from "./LibAsset.sol"; 171 import { LibUtil } from "./LibUtil.sol"; 172 library LibSwap { 173 uint256 private constant MAX_INT = 2**256 - 1; 174 struct SwapData { 175 address callTo; 176 address approveTo; 177 address sendingAssetId; 178 address receivingAssetId; 179 uint256 fromAmount; 180 bytes callData; 181 } 182 event AssetSwapped( 183 bytes32 transactionId, 184 address dex, 185 address fromAssetId, 186 address toAssetId, 187 uint256 fromAmount, 188 uint256 toAmount, 189 uint256 timestamp 190 ); 191 function swap(bytes32 transactionId, SwapData calldata _swapData, bool invokeSwap) internal { 192 uint256 fromAmount = _swapData.fromAmount; 193 uint256 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId); 194 address fromAssetId = _swapData.sendingAssetId; 195 if (!LibAsset.isNativeAsset(fromAssetId) && LibAsset.getOwnBalance(fromAssetId) < fromAmount) { 196 LibAsset.transferFromERC20(_swapData.sendingAssetId, msg.sender, address(this), fromAmount); 197 } 198 if (!LibAsset.isNativeAsset(fromAssetId)) { 199 LibAsset.approveERC20(IERC20(fromAssetId), _swapData.approveTo, fromAmount); 200 } 201 // solhint-disable-next-line avoid-low-level-calls 202 (bool success, bytes memory res) = _swapData.callTo.call{ value: msg.value }(_swapData.callData); 203 if (!success) { 204 string memory reason = LibUtil.getRevertMsg(res); 205 revert(reason); 206 } 207 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId) - toAmount; 208 emit AssetSwapped( 209 transactionId, 210 _swapData.callTo, 211 _swapData.sendingAssetId, 212 _swapData.receivingAssetId, 213 fromAmount, 214 toAmount, 215 block.timestamp 216 ); 217 } 218 } | 58+ require(msg.value >= _cBridgeData.amount, "ERR_INVALID_AMOUNT"); 92+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 101+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 125+ require(s.cBridgeChainId != _cBridgeData.dstChainId, "Cannot bridge to the same network."); 191+ assert(!invokeSwap); | 125+ | require(s.cBridgeChainId != _cBridgeData.dstChainId, "Cannot bridge to the same network."); | |||||||||||||||||||||||
90 | 1 // SPDX-License-Identifier: MIT 2 pragma solidity ^0.8.7; 3 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 4 import { LibAsset } from "../Libraries/LibAsset.sol"; 5 import { ILiFi } from "../Interfaces/ILiFi.sol"; 6 import { LibSwap } from "../Libraries/LibSwap.sol"; 7 import { ICBridge } from "../Interfaces/ICBridge.sol"; 8 import { LibDiamond } from "../Libraries/LibDiamond.sol"; 9 /** 10 * @title CBridge Facet 11 * @author Li.Finance (https://li.finance) 12 * @notice Provides functionality for bridging through CBridge 13 */ 14 contract CBridgeFacet is ILiFi { 15 /* ========== Storage ========== */ 16 bytes32 internal constant NAMESPACE = keccak256("com.lifi.facets.cbridge2"); 17 invokeSwap bool; 18 struct Storage { 19 address cBridge; 20 uint64 cBridgeChainId; 21 } 22 /* ========== Types ========== */ 23 struct CBridgeData { 24 address receiver; 25 address token; 26 uint256 amount; 27 uint64 dstChainId; 28 uint64 nonce; 29 uint32 maxSlippage; 30 } 31 /* ========== Init ========== */ 32 /** 33 * @notice Initializes local variables for the CBridge facet 34 * @param _cBridge address of the canonical CBridge router contract 35 * @param _chainId chainId of this deployed contract 36 */ 37 function initCbridge(address _cBridge, uint64 _chainId) external { 38 Storage storage s = getStorage(); 39 LibDiamond.enforceIsContractOwner(); 40 s.cBridge = _cBridge; 41 s.cBridgeChainId = _chainId; 42 emit Inited(s.cBridge, s.cBridgeChainId); 43 } 44 /* ========== Public Bridge Functions ========== */ 45 /** 46 * @notice Bridges tokens via CBridge 47 * @param _lifiData data used purely for tracking and analytics 48 * @param _cBridgeData data specific to CBridge 49 */ 50 function startBridgeTokensViaCBridge(LiFiData memory _lifiData, CBridgeData calldata _cBridgeData) public payable { 51 if (_cBridgeData.token != address(0)) { 52 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 53 LibAsset.transferFromERC20(_cBridgeData.token, msg.sender, address(this), _cBridgeData.amount); 54 require( 55 LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance == _cBridgeData.amount, 56 "ERR_INVALID_AMOUNT" 57 ); 58 } else { 59 _; 60 } 61 _startBridge(_cBridgeData); 62 emit LiFiTransferStarted( 63 _lifiData.transactionId, 64 _lifiData.integrator, 65 _lifiData.referrer, 66 _lifiData.sendingAssetId, 67 _lifiData.receivingAssetId, 68 _lifiData.receiver, 69 _lifiData.amount, 70 _lifiData.destinationChainId, 71 block.timestamp 72 ); 73 } 74 /** 75 * @notice Performs a swap before bridging via CBridge 76 * @param _lifiData data used purely for tracking and analytics 77 * @param _swapData an array of swap related data for performing swaps before bridging 78 * @param _cBridgeData data specific to CBridge 79 */ 80 function swapAndStartBridgeTokensViaCBridge( 81 LiFiData memory _lifiData, 82 LibSwap.SwapData[] calldata _swapData, 83 CBridgeData memory _cBridgeData 84 ) public payable { 85 if (_cBridgeData.token != address(0)) { 86 uint256 _fromTokenBalance = LibAsset.getOwnBalance(_cBridgeData.token); 87 // Swap 88 for (uint8 i; i < _swapData.length; i++) { 89 invokeSwap = true; 90 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 91 } 92 uint256 _postSwapBalance = LibAsset.getOwnBalance(_cBridgeData.token) - _fromTokenBalance; 93 _cBridgeData.amount = _postSwapBalance; 94 } else { 95 uint256 _fromBalance = address(this).balance; 96 // Swap 97 for (uint8 i; i < _swapData.length; i++) { 98 invokeSwap = true; 99 LibSwap.swap(_lifiData.transactionId, _swapData[i], invokeSwap); 100 } 101 uint256 _postSwapBalance = address(this).balance - _fromBalance; 102 _cBridgeData.amount = _postSwapBalance; 103 } 104 _startBridge(_cBridgeData); 105 emit LiFiTransferStarted( 106 _lifiData.transactionId, 107 _lifiData.integrator, 108 _lifiData.referrer, 109 _lifiData.sendingAssetId, 110 _lifiData.receivingAssetId, 111 _lifiData.receiver, 112 _lifiData.amount, 113 _lifiData.destinationChainId, 114 block.timestamp 115 ); 116 } 117 /* ========== Internal Functions ========== */ 118 /* 119 * @dev Conatains the business logic for the bridge via CBridge 120 * @param _cBridgeData data specific to CBridge 121 */ 122 function _startBridge(CBridgeData memory _cBridgeData) internal { 123 Storage storage s = getStorage(); 124 address bridge = _bridge(); 125 // Do CBridge stuff 126 if (LibAsset.isNativeAsset(_cBridgeData.token)) { 127 ICBridge(bridge).sendNative( 128 _cBridgeData.receiver, 129 _cBridgeData.amount, 130 _cBridgeData.dstChainId, 131 _cBridgeData.nonce, 132 _cBridgeData.maxSlippage 133 ); 134 } else { 135 // Give CBridge approval to bridge tokens 136 LibAsset.approveERC20(IERC20(_cBridgeData.token), bridge, _cBridgeData.amount); 137 // solhint-disable check-send-result 138 ICBridge(bridge).send( 139 _cBridgeData.receiver, 140 _cBridgeData.token, 141 _cBridgeData.amount, 142 _cBridgeData.dstChainId, 143 _cBridgeData.nonce, 144 _cBridgeData.maxSlippage 145 ); 146 } 147 } 148 /* 149 * @dev Public view function for the CBridge router address 150 * @returns the router address 151 */ 152 function _bridge() internal view returns (address) { 153 Storage storage s = getStorage(); 154 return s.cBridge; 155 } 156 /** 157 * @dev fetch local storage 158 */ 159 function getStorage() internal pure returns (Storage storage s) { 160 bytes32 namespace = NAMESPACE; 161 // solhint-disable-next-line no-inline-assembly 162 assembly { 163 s.slot := namespace 164 } 165 } 166 } 167 // SPDX-License-Identifier: MIT 168 pragma solidity ^0.8.7; 169 import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; 170 import { LibAsset } from "./LibAsset.sol"; 171 import { LibUtil } from "./LibUtil.sol"; 172 library LibSwap { 173 uint256 private constant MAX_INT = 2**256 - 1; 174 struct SwapData { 175 address callTo; 176 address approveTo; 177 address sendingAssetId; 178 address receivingAssetId; 179 uint256 fromAmount; 180 bytes callData; 181 } 182 event AssetSwapped( 183 bytes32 transactionId, 184 address dex, 185 address fromAssetId, 186 address toAssetId, 187 uint256 fromAmount, 188 uint256 toAmount, 189 uint256 timestamp 190 ); 191 function swap(bytes32 transactionId, SwapData calldata _swapData, bool invokeSwap) internal { 192 uint256 fromAmount = _swapData.fromAmount; 193 uint256 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId); 194 address fromAssetId = _swapData.sendingAssetId; 195 if (!LibAsset.isNativeAsset(fromAssetId) && LibAsset.getOwnBalance(fromAssetId) < fromAmount) { 196 LibAsset.transferFromERC20(_swapData.sendingAssetId, msg.sender, address(this), fromAmount); 197 } 198 if (!LibAsset.isNativeAsset(fromAssetId)) { 199 LibAsset.approveERC20(IERC20(fromAssetId), _swapData.approveTo, fromAmount); 200 } 201 // solhint-disable-next-line avoid-low-level-calls 202 (bool success, bytes memory res) = _swapData.callTo.call{ value: msg.value }(_swapData.callData); 203 if (!success) { 204 string memory reason = LibUtil.getRevertMsg(res); 205 revert(reason); 206 } 207 toAmount = LibAsset.getOwnBalance(_swapData.receivingAssetId) - toAmount; 208 emit AssetSwapped( 209 transactionId, 210 _swapData.callTo, 211 _swapData.sendingAssetId, 212 _swapData.receivingAssetId, 213 fromAmount, 214 toAmount, 215 block.timestamp 216 ); 217 } 218 } | 58+ require(msg.value >= _cBridgeData.amount, "ERR_INVALID_AMOUNT"); 92+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 101+ require(_postSwapBalance > 0, "ERR_INVALID_AMOUNT"); 125+ require(s.cBridgeChainId != _cBridgeData.dstChainId, "Cannot bridge to the same network."); 191+ assert(!invokeSwap); | 191+ | assert(!invokeSwap); | |||||||||||||||||||||||
91 | 1 // SPDX-License-Identifier: MIT OR Apache-2.0 2 pragma solidity >=0.6.11; 3 */ 4 contract Replica { 5 /** 6 * @notice Emitted when message is processed 7 * @param messageHash Hash of message that failed to process 8 * @param success TRUE if the call was executed successfully, FALSE if the call reverted 9 * @param returnData the return data from the external call 10 */ 11 event Process( 12 bytes32 indexed messageHash, 13 bool indexed success, 14 bytes indexed returnData 15 ); 16 function initialize( 17 uint32 _remoteDomain, 18 address _updater, 19 bytes32 _committedRoot, 20 uint256 _optimisticSeconds 21 ) public initializer { 22 __NomadBase_initialize(_updater); 23 // set storage variables 24 entered = 1; 25 remoteDomain = _remoteDomain; 26 committedRoot = _committedRoot; 27 confirmAt[_committedRoot] = 1; 28 optimisticSeconds = _optimisticSeconds; 29 emit SetOptimisticTimeout(_optimisticSeconds); 30 } 31 // ============ External Functions ============ 32 /** 33 * @notice Called by external agent. Submits the signed update's new root, 34 * marks root's allowable confirmation time, and emits an `Update` event. 35 * @dev Reverts if update doesn't build off latest committedRoot 36 * or if signature is invalid. 37 * @param _oldRoot Old merkle root 38 * @param _newRoot New merkle root 39 * @param _signature Updater's signature on `_oldRoot` and `_newRoot` 40 */ 41 function update( 42 bytes32 _oldRoot, 43 bytes32 _newRoot, 44 bytes memory _signature 45 ) external notFailed { 46 // ensure that update is building off the last submitted root 47 require(_oldRoot == committedRoot, "not current update"); 48 // validate updater signature 49 require( 50 _isUpdaterSignature(_oldRoot, _newRoot, _signature), 51 "!updater sig" 52 ); 53 // Hook for future use 54 _beforeUpdate(); 55 // set the new root's confirmation timer 56 confirmAt[_newRoot] = block.timestamp + optimisticSeconds; 57 // update committedRoot 58 committedRoot = _newRoot; 59 emit Update(remoteDomain, _oldRoot, _newRoot, _signature); 60 } 61 /** 62 * @notice First attempts to prove the validity of provided formatted 63 * `message`. If the message is successfully proven, then tries to process 64 * message. 65 * @dev Reverts if `prove` call returns false 66 * @param _message Formatted message (refer to NomadBase.sol Message library) 67 * @param _proof Merkle proof of inclusion for message's leaf 68 * @param _index Index of leaf in home's merkle tree 69 */ 70 function proveAndProcess( 71 bytes memory _message, 72 bytes32[32] calldata _proof, 73 uint256 _index 74 ) external { 75 require(prove(keccak256(_message), _proof, _index), "!prove"); 76 process(_message); 77 } 78 /** 79 * @notice Given formatted message, attempts to dispatch 80 * message payload to end recipient. 81 * @dev Recipient must implement a `handle` method (refer to IMessageRecipient.sol) 82 * Reverts if formatted message's destination domain is not the Replica's domain, 83 * if message has not been proven, 84 * or if not enough gas is provided for the dispatch transaction. 85 * @param _message Formatted message 86 * @return _success TRUE iff dispatch transaction succeeded 87 */ 88 function process(bytes memory _message) public returns (bool _success) { 89 bytes29 _m = _message.ref(0); 90 // ensure message was meant for this domain 91 require(_m.destination() == localDomain, "!destination"); 92 // ensure message has been proven 93 bytes32 _messageHash = _m.keccak(); 94 require(messages[_messageHash] == MessageStatus.Proven, "!proven"); 95 // check re-entrancy guard 96 require(entered == 1, "!reentrant"); 97 entered = 0; 98 // update message status as processed 99 messages[_messageHash] = MessageStatus.Processed; 100 // A call running out of gas TYPICALLY errors the whole tx. We want to 101 // a) ensure the call has a sufficient amount of gas to make a 102 // meaningful state change. 103 // b) ensure that if the subcall runs out of gas, that the tx as a whole 104 // does not revert (i.e. we still mark the message processed) 105 // To do this, we require that we have enough gas to process 106 // and still return. We then delegate only the minimum processing gas. 107 require(gasleft() >= PROCESS_GAS + RESERVE_GAS, "!gas"); 108 // get the message recipient 109 address _recipient = _m.recipientAddress(); 110 // set up for assembly call 111 uint256 _toCopy; 112 uint256 _maxCopy = 256; 113 uint256 _gas = PROCESS_GAS; 114 // allocate memory for returndata 115 bytes memory _returnData = new bytes(_maxCopy); 116 bytes memory _calldata = abi.encodeWithSignature( 117 "handle(uint32,uint32,bytes32,bytes)", 118 _m.origin(), 119 _m.nonce(), 120 _m.sender(), 121 _m.body().clone() 122 ); 123 // dispatch message to recipient 124 // by assembly calling "handle" function 125 // we call via assembly to avoid memcopying a very large returndata 126 // returned by a malicious contract 127 assembly { 128 _success := call( 129 _gas, // gas 130 _recipient, // recipient 131 0, // ether value 132 add(_calldata, 0x20), // inloc 133 mload(_calldata), // inlen 134 0, // outloc 135 0 // outlen 136 ) 137 // limit our copy to 256 bytes 138 _toCopy := returndatasize() 139 if gt(_toCopy, _maxCopy) { 140 _toCopy := _maxCopy 141 } 142 // Store the length of the copied bytes 143 mstore(_returnData, _toCopy) 144 // copy the bytes from returndata[0:_toCopy] 145 returndatacopy(add(_returnData, 0x20), 0, _toCopy) 146 } 147 // emit process results 148 emit Process(_messageHash, _success, _returnData); 149 // reset re-entrancy guard 150 entered = 1; 151 } 152 // ============ External Owner Functions ============ 153 /** 154 * @notice Set optimistic timeout period for new roots 155 * @dev Only callable by owner (Governance) 156 * @param _optimisticSeconds New optimistic timeout period 157 */ 158 function setOptimisticTimeout(uint256 _optimisticSeconds) 159 external 160 onlyOwner 161 { 162 optimisticSeconds = _optimisticSeconds; 163 emit SetOptimisticTimeout(_optimisticSeconds); 164 } 165 /** 166 * @notice Set Updater role 167 * @dev MUST ensure that all roots signed by previous Updater have 168 * been relayed before calling. Only callable by owner (Governance) 169 * @param _updater New Updater 170 */ 171 function setUpdater(address _updater) external onlyOwner { 172 _setUpdater(_updater); 173 } 174 /** 175 * @notice Set confirmAt for a given root 176 * @dev To be used if in the case that fraud is proven 177 * and roots need to be deleted / added. Only callable by owner (Governance) 178 * @param _root The root for which to modify confirm time 179 * @param _confirmAt The new confirmation time. Set to 0 to "delete" a root. 180 */ 181 function setConfirmation(bytes32 _root, uint256 _confirmAt) 182 external 183 onlyOwner 184 { 185 uint256 _previousConfirmAt = confirmAt[_root]; 186 confirmAt[_root] = _confirmAt; 187 emit SetConfirmation(_root, _previousConfirmAt, _confirmAt); 188 } 189 // ============ Public Functions ============ 190 /** 191 * @notice Check that the root has been submitted 192 * and that the optimistic timeout period has expired, 193 * meaning the root can be processed 194 * @param _root the Merkle root, submitted in an update, to check 195 * @return TRUE iff root has been submitted & timeout has expired 196 */ 197 function acceptableRoot(bytes32 _root) public view returns (bool) { 198 uint256 _time = confirmAt[_root]; 199 if (_time == 0) { 200 return false; 201 } 202 return block.timestamp >= _time; 203 } 204 /** 205 * @notice Attempts to prove the validity of message given its leaf, the 206 * merkle proof of inclusion for the leaf, and the index of the leaf. 207 * @dev Reverts if message's MessageStatus != None (i.e. if message was 208 * already proven or processed) 209 * @dev For convenience, we allow proving against any previous root. 210 * This means that witnesses never need to be updated for the new root 211 * @param _leaf Leaf of message to prove 212 * @param _proof Merkle proof of inclusion for leaf 213 * @param _index Index of leaf in home's merkle tree 214 * @return Returns true if proof was valid and `prove` call succeeded 215 **/ 216 function prove( 217 bytes32 _leaf, 218 bytes32[32] calldata _proof, 219 uint256 _index 220 ) public returns (bool) { 221 // ensure that message has not been proven or processed 222 require(messages[_leaf] == MessageStatus.None, "!MessageStatus.None"); 223 // calculate the expected root based on the proof 224 bytes32 _calculatedRoot = MerkleLib.branchRoot(_leaf, _proof, _index); 225 // if the root is valid, change status to Proven 226 if (acceptableRoot(_calculatedRoot)) { 227 messages[_leaf] = MessageStatus.Proven; 228 return true; 229 } 230 return false; 231 } 232 /** 233 * @notice Hash of Home domain concatenated with "NOMAD" 234 */ 235 function homeDomainHash() public view override returns (bytes32) { 236 return _homeDomainHash(remoteDomain); 237 } 238 // ============ Internal Functions ============ 239 /** 240 * @notice Moves the contract into failed state 241 * @dev Called when a Double Update is submitted 242 */ 243 function _fail() internal override { 244 _setFailed(); 245 } 246 /// @notice Hook for potential future use 247 // solhint-disable-next-line no-empty-blocks 248 function _beforeUpdate() internal {} 249 } | 26+ assert(_committedRoot != 0); | 26+ | assert(_committedRoot != 0) | |||||||||||||||||||||||
92 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 29+ | require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); | |||||||||||||||||||||||
93 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 30+ | require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); | |||||||||||||||||||||||
94 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 48+ | require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); | |||||||||||||||||||||||
95 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 51+ | require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); | |||||||||||||||||||||||
96 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 54+ | require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); | |||||||||||||||||||||||
97 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 55+ | require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); | |||||||||||||||||||||||
98 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 83+ | require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); | |||||||||||||||||||||||
99 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 106+ | require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); | |||||||||||||||||||||||
100 | 1 pragma solidity ^0.5.0; 2 import "./../../../libs/math/SafeMath.sol"; 3 import "./../../../libs/common/ZeroCopySource.sol"; 4 import "./../../../libs/common/ZeroCopySink.sol"; 5 import "./../../../libs/utils/Utils.sol"; 6 import "./../upgrade/UpgradableECCM.sol"; 7 import "./../libs/EthCrossChainUtils.sol"; 8 import "./../interface/IEthCrossChainManager.sol"; 9 import "./../interface/IEthCrossChainData.sol"; 10 contract EthCrossChainManager is IEthCrossChainManager, UpgradableECCM { 11 using SafeMath for uint256; 12 event InitGenesisBlockEvent(uint256 height, bytes rawHeader); 13 event ChangeBookKeeperEvent(uint256 height, bytes rawHeader); 14 event CrossChainEvent(address indexed sender, bytes txId, address proxyOrAssetContract, uint64 toChainId, bytes toContract, bytes rawdata); 15 event VerifyHeaderAndExecuteTxEvent(uint64 fromChainID, bytes toContract, bytes crossChainTxHash, bytes fromChainTxHash); 16 constructor(address _eccd) UpgradableECCM(_eccd) public {} 17 /* @notice sync Poly chain genesis block header to smart contrat 18 * @dev this function can only be called once, nextbookkeeper of rawHeader can't be empty 19 * @param rawHeader Poly chain genesis block raw header or raw Header including switching consensus peers info 20 * @return true or false 21 */ 22 function initGenesisBlock(bytes memory rawHeader, bytes memory pubKeyList) whenNotPaused public returns(bool) { 23 // Load Ethereum cross chain data contract 24 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 25 // Make sure the contract has not been initialized before 26 require(eccd.getCurEpochConPubKeyBytes().length == 0, "EthCrossChainData contract has already been initialized!"); 27 // Parse header and convit the public keys into nextBookKeeper and compare it with header.nextBookKeeper to verify the validity of signature 28 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 29 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 30 // Record current epoch start height and public keys (by storing them in address format) 31 // Fire the event 32 emit InitGenesisBlockEvent(header.height, rawHeader); 33 return true; 34 } 35 /* @notice change Poly chain consensus book keeper 36 * @param rawHeader Poly chain change book keeper block raw header 37 * @param pubKeyList Poly chain consensus nodes public key list 38 * @param sigList Poly chain consensus nodes signature list 39 * @return true or false 40 */ 41 function changeBookKeeper(bytes memory rawHeader, bytes memory pubKeyList, bytes memory sigList) whenNotPaused public returns(bool) { 42 // Load Ethereum cross chain data contract 43 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 44 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 45 // Make sure rawHeader.height is higher than recorded current epoch start height 46 uint64 curEpochStartHeight = eccd.getCurEpochStartHeight(); 47 require(header.height > curEpochStartHeight, "The height of header is lower than current epoch start height!"); 48 // Ensure the rawHeader is the key header including info of switching consensus peers by containing non-empty nextBookKeeper field 49 // Verify signature of rawHeader comes from pubKeyList 50 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 51 uint n = polyChainBKs.length; 52 // Convert pubKeyList into ethereum address format and make sure the compound address from the converted ethereum addresses 53 // equals passed in header.nextBooker 54 (bytes20 nextBookKeeper, address[] memory keepers) = ECCUtils.verifyPubkey(pubKeyList); 55 // update current epoch start height of Poly chain and current epoch consensus peers book keepers addresses 56 // Fire the change book keeper event 57 emit ChangeBookKeeperEvent(header.height, rawHeader); 58 return true; 59 } 60 /* @notice ERC20 token cross chain to other blockchain. 61 * this function push tx event to blockchain 62 * @param toChainId Target chain id 63 * @param toContract Target smart contract address in target block chain 64 * @param txData Transaction data for target chain, include to_address, amount 65 * @return true or false 66 */ 67 function crossChain(uint64 toChainId, bytes calldata toContract, bytes calldata method, bytes calldata txData) whenNotPaused external returns (bool) { 68 // Load Ethereum cross chain data contract 69 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 70 // To help differentiate two txs, the ethTxHashIndex is increasing automatically 71 uint256 txHashIndex = eccd.getEthTxHashIndex(); 72 // Convert the uint256 into bytes 73 bytes memory paramTxHash = Utils.uint256ToBytes(txHashIndex); 74 // Construct the makeTxParam, and put the hash info storage, to help provide proof of tx existence 75 bytes memory rawParam = abi.encodePacked(ZeroCopySink.WriteVarBytes(paramTxHash), 76 ZeroCopySink.WriteVarBytes(abi.encodePacked(sha256(abi.encodePacked(address(this), paramTxHash)))), 77 ZeroCopySink.WriteVarBytes(Utils.addressToBytes(msg.sender)), 78 ZeroCopySink.WriteUint64(toChainId), 79 ZeroCopySink.WriteVarBytes(toContract), 80 ZeroCopySink.WriteVarBytes(method), 81 ZeroCopySink.WriteVarBytes(txData) 82 ); 83 // Must save it in the storage to be included in the proof to be verified. 84 // Fire the cross chain event denoting there is a cross chain request from Ethereum network to other public chains through Poly chain network 85 emit CrossChainEvent(tx.origin, paramTxHash, msg.sender, toChainId, toContract, rawParam); 86 return true; 87 } 88 /* @notice Verify Poly chain header and proof, execute the cross chain tx from Poly chain to Ethereum 89 * @param proof Poly chain tx merkle proof 90 * @param rawHeader The header containing crossStateRoot to verify the above tx merkle proof 91 * @param headerProof The header merkle proof used to verify rawHeader 92 * @param curRawHeader Any header in current epoch consensus of Poly chain 93 * @param headerSig The coverted signature veriable for solidity derived from Poly chain consensus nodes' signature 94 * used to verify the validity of curRawHeader 95 * @return true or false 96 */ 97 function verifyHeaderAndExecuteTx(bytes memory proof, bytes memory rawHeader, bytes memory headerProof, bytes memory curRawHeader,bytes memory headerSig) whenNotPaused public returns (bool){ 98 ECCUtils.Header memory header = ECCUtils.deserializeHeader(rawHeader); 99 // Load ehereum cross chain data contract 100 IEthCrossChainData eccd = IEthCrossChainData(EthCrossChainDataAddress); 101 // Get stored consensus public key bytes of current poly chain epoch and deserialize Poly chain consensus public key bytes to address[] 102 address[] memory polyChainBKs = ECCUtils.deserializeKeepers(eccd.getCurEpochConPubKeyBytes()); 103 uint256 curEpochStartHeight = eccd.getCurEpochStartHeight(); 104 uint n = polyChainBKs.length; 105 if (header.height >= curEpochStartHeight) { 106 // It's enough to verify rawHeader signature 107 } else { 108 // We need to verify the signature of curHeader 109 _; 110 // Then use curHeader.StateRoot and headerProof to verify rawHeader.CrossStateRoot 111 ECCUtils.Header memory curHeader = ECCUtils.deserializeHeader(curRawHeader); 112 bytes memory proveValue = ECCUtils.merkleProve(headerProof, curHeader.blockRoot); 113 } 114 // Through rawHeader.CrossStatesRoot, the toMerkleValue or cross chain msg can be verified and parsed from proof 115 bytes memory toMerkleValueBs = ECCUtils.merkleProve(proof, header.crossStatesRoot); 116 // Parse the toMerkleValue struct and make sure the tx has not been processed, then mark this tx as processed 117 ECCUtils.ToMerkleValue memory toMerkleValue = ECCUtils.deserializeMerkleValue(toMerkleValueBs); 118 // Ethereum ChainId is 2, we need to check the transaction is for Ethereum network 119 // Obtain the targeting contract, so that Ethereum cross chain manager contract can trigger the executation of cross chain tx on Ethereum side 120 address toContract = Utils.bytesToAddress(toMerkleValue.makeTxParam.toContract); 121 //TODO: check this part to make sure we commit the next line when doing local net UT test 122 // Fire the cross chain event denoting the executation of cross chain tx is successful, 123 // and this tx is coming from other public chains to current Ethereum network 124 emit VerifyHeaderAndExecuteTxEvent(toMerkleValue.fromChainID, toMerkleValue.makeTxParam.toContract, toMerkleValue.txHash, toMerkleValue.makeTxParam.txHash); 125 return true; 126 } 127 /* @notice Dynamically invoke the targeting contract, and trigger executation of cross chain tx on Ethereum side 128 * @param _toContract The targeting contract that will be invoked by the Ethereum Cross Chain Manager contract 129 * @param _method At which method will be invoked within the targeting contract 130 * @param _args The parameter that will be passed into the targeting contract 131 * @param _fromContractAddr From chain smart contract address 132 * @param _fromChainId Indicate from which chain current cross chain tx comes 133 * @return true or false 134 */ 135 function _executeCrossChainTx(address _toContract, bytes memory _method, bytes memory _args, bytes memory _fromContractAddr, uint64 _fromChainId) internal returns (bool){ 136 // Ensure the targeting contract gonna be invoked is indeed a contract rather than a normal account address 137 require(Utils.isContract(_toContract), "The passed in address is not a contract!"); 138 bytes memory returnData; 139 bool success; 140 // The returnData will be bytes32, the last byte must be 01; 141 (success, returnData) = _toContract.call(abi.encodePacked(bytes4(keccak256(abi.encodePacked(_method, "(bytes,bytes,uint64)"))), abi.encode(_args, _fromContractAddr, _fromChainId))); 142 // Ensure the executation is successful 143 // Ensure the returned value is true 144 require(returnData.length != 0, "No return value from business contract!"); 145 (bool res,) = ZeroCopySource.NextBool(returnData, 31); 146 return true; 147 } 148 } | 29+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 30+ require(eccd.putCurEpochStartHeight(header.height), "Save Poly chain current epoch start height to Data contract failed!"); 30+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain current epoch book keepers to Data contract failed!"); 48+ require(header.nextBookkeeper != bytes20(0), "The nextBookKeeper of header is empty"); 51+ require(ECCUtils.verifySig(rawHeader, sigList, polyChainBKs, n - (n - 1) / 3), "Verify signature failed!"); 54+ require(header.nextBookkeeper == nextBookKeeper, "NextBookers illegal"); 55+ require(eccd.putCurEpochStartHeight(header.height), "Save MC LatestHeight to Data contract failed!"); 55+ require(eccd.putCurEpochConPubKeyBytes(ECCUtils.serializeKeepers(keepers)), "Save Poly chain book keepers bytes to Data contract failed!"); 83+ require(eccd.putEthTxHash(keccak256(rawParam)), "Save ethTxHash by index to Data contract failed!"); 106+ require(ECCUtils.verifySig(rawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain header signature failed!"); 108+ require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); 112+ require(ECCUtils.getHeaderHash(rawHeader) == Utils.bytesToBytes32(proveValue), "verify header proof failed!"); 117+ require(!eccd.checkIfFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "the transaction has been executed!"); 117+ require(eccd.markFromChainTxExist(toMerkleValue.fromChainID, Utils.bytesToBytes32(toMerkleValue.txHash)), "Save crosschain tx exist failed!"); 118+ require(toMerkleValue.makeTxParam.toChainId == uint64(2), "This Tx is not aiming at Ethereum network!"); 121+ require(_executeCrossChainTx(toContract, toMerkleValue.makeTxParam.method, toMerkleValue.makeTxParam.args, toMerkleValue.makeTxParam.fromContract, toMerkleValue.fromChainID), "Execute CrossChain Tx failed!"); 139+ assert(_method != “f1121318093”); 143+ require(success == true, "EthCrossChain call business contract failed"); 145+ require(res == true, "EthCrossChain call business contract return is not true"); | 108+ | require(ECCUtils.verifySig(curRawHeader, headerSig, polyChainBKs, n - ( n - 1) / 3), "Verify poly chain current epoch header signature failed!"); |