ABCDEFGHIJKLMNOPQRSTUVWXYZAA
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!");