Overview
SOPH Balance
SOPH Value
-More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
1746266 | 34 days ago | Contract Creation | 0 SOPH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
SophonFarmingL2
Compiler Version
v0.8.26+commit.8a97fa7a
ZkSolc Version
v1.5.6
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; import "contracts/token/ERC20/utils/SafeERC20.sol"; import "contracts/token/ERC20/extensions/IERC20Metadata.sol"; import "contracts/utils/cryptography/MerkleProof.sol"; import "contracts/utils/math/Math.sol"; import "contracts/farm/interfaces/IWeth.sol"; import "contracts/farm/interfaces/IstETH.sol"; import "contracts/farm/interfaces/IwstETH.sol"; import "contracts/farm/interfaces/IsDAI.sol"; import "contracts/farm/interfaces/IeETHLiquidityPool.sol"; import "contracts/farm/interfaces/IweETH.sol"; import "contracts/farm/interfaces/IPriceFeeds.sol"; import "contracts/proxies/Upgradeable2Step.sol"; import "contracts/farm/SophonFarmingState.sol"; /** * @title Sophon Farming Contract * @author Sophon */ contract SophonFarmingL2 is Upgradeable2Step, SophonFarmingState { using SafeERC20 for IERC20; /// @notice Emitted when a new pool is added event Add(address indexed lpToken, uint256 indexed pid, uint256 allocPoint); /// @notice Emitted when a pool is updated event Set(address indexed lpToken, uint256 indexed pid, uint256 allocPoint); /// @notice Emitted when a user deposits to a pool event Deposit(address indexed user, uint256 indexed pid, uint256 depositAmount, uint256 boostAmount); /// @notice Emitted when a user withdraws from a pool event Withdraw(address indexed user, uint256 indexed pid, uint256 amount); /// @notice Emitted when a whitelisted admin transfers points from one user to another event TransferPoints(address indexed sender, address indexed receiver, uint256 indexed pid, uint256 amount); /// @notice Emitted when a user increases the boost of an existing deposit event IncreaseBoost(address indexed user, uint256 indexed pid, uint256 boostAmount); /// @notice Emitted when the the updatePool function is called event PoolUpdated(uint256 indexed pid, uint256 currentValue, uint256 newPrice); /// @notice Emitted when setPointsPerBlock is called event SetPointsPerBlock(uint256 oldValue, uint256 newValue); /// @notice Emitted when setEmissionsMultiplier is called event SetEmissionsMultiplier(uint256 oldValue, uint256 newValue); /// @notice Emitted when held proceeds are withdrawn event WithdrawHeldProceeds(uint256 indexed pid, address indexed to, uint256 amount); error ZeroAddress(); error PoolExists(); error PoolDoesNotExist(); error AlreadyInitialized(); error NotFound(address lpToken); error FarmingIsStarted(); error FarmingIsEnded(); error TransferNotAllowed(); error TransferTooHigh(uint256 maxAllowed); error InvalidEndBlock(); error InvalidDeposit(); error InvalidPointsPerBlock(); error InvalidTransfer(); error WithdrawNotAllowed(); error WithdrawTooHigh(uint256 maxAllowed); error WithdrawIsZero(); error NothingInPool(); error NoEthSent(); error BridgeInvalid(); error OnlyMerkle(); error CountMismatch(); address public immutable MERKLE; IPriceFeeds public immutable priceFeeds; /** * @notice Construct SophonFarming */ constructor(address _MERKLE, address _priceFeeds) { if (_MERKLE == address(0)) revert ZeroAddress(); MERKLE = _MERKLE; if (_priceFeeds == address(0)) revert ZeroAddress(); priceFeeds = IPriceFeeds(_priceFeeds); } /** * @notice Withdraw heldProceeds for a given pool * @param _pid The pool ID to withdraw from * @param _to The address that will receive the tokens */ function withdrawHeldProceeds(uint256 _pid, address _to) external onlyOwner { if (_to == address(0)) revert ZeroAddress(); uint256 amount = heldProceeds[_pid]; if (amount == 0) revert NothingInPool(); // Transfer the tokens to the specified address poolInfo[_pid].lpToken.safeTransfer(_to, amount); // Reset the mapping for that pid heldProceeds[_pid] = 0; emit WithdrawHeldProceeds(_pid, _to, amount); } function updateUserInfo(address _user, uint256 _pid, UserInfo memory _userFromClaim) external { if (msg.sender != MERKLE) revert OnlyMerkle(); require(_pid < poolInfo.length, "Invalid pool id"); require(_userFromClaim.amount == _userFromClaim.boostAmount + _userFromClaim.depositAmount, "balances don't match"); massUpdatePools(); UserInfo storage user = userInfo[_pid][_user]; uint256 accPointsPerShare = poolInfo[_pid].accPointsPerShare; user.amount = user.amount + _userFromClaim.amount; // handles rewards for deposits before claims and for backdated rewards on claimed amounts user.rewardSettled = user.amount * accPointsPerShare / 1e18 + user.rewardSettled - user.rewardDebt; user.rewardSettled = user.rewardSettled + _userFromClaim.rewardSettled; user.boostAmount = user.boostAmount + _userFromClaim.boostAmount; user.depositAmount = user.depositAmount + _userFromClaim.depositAmount; user.rewardDebt = user.amount * accPointsPerShare / 1e18; } /** * @notice Adds a new pool to the farm. Can only be called by the owner. * @param _lpToken lpToken address * @param _emissionsMultiplier multiplier for emissions fine tuning; use 0 or 1e18 for 1x * @param _description description of new pool * @param _poolStartBlock block at which points start to accrue for the pool * @param _newPointsPerBlock update global points per block; 0 means no update * @return uint256 The pid of the newly created asset */ function add(address _lpToken, uint256 _emissionsMultiplier, string memory _description, uint256 _poolStartBlock, uint256 _newPointsPerBlock) public onlyOwner returns (uint256) { if (_lpToken == address(0)) { revert ZeroAddress(); } if (poolExists[_lpToken]) { revert PoolExists(); } if (isFarmingEnded()) { revert FarmingIsEnded(); } if (_newPointsPerBlock != 0) { setPointsPerBlock(_newPointsPerBlock); } else { massUpdatePools(); } uint256 lastRewardBlock = getBlockNumber() > _poolStartBlock ? getBlockNumber() : _poolStartBlock; poolExists[_lpToken] = true; uint256 pid = poolInfo.length; poolInfo.push( PoolInfo({ lpToken: IERC20(_lpToken), l2Farm: address(0), amount: 0, boostAmount: 0, depositAmount: 0, allocPoint: 0, lastRewardBlock: lastRewardBlock, accPointsPerShare: 0, totalRewards: 0, description: _description }) ); if (_emissionsMultiplier == 0) { // set multiplier to 1x _emissionsMultiplier = 1e18; } poolValue[pid].emissionsMultiplier = _emissionsMultiplier; emit Add(_lpToken, pid, 0); return pid; } /** * @notice Updates the given pool's allocation point. Can only be called by the owner. * @param _pid The pid to update * @param _emissionsMultiplier multiplier for emissions fine tuning; use 0 for no update OR 1e18 for 1x * @param _poolStartBlock block at which points start to accrue for the pool; 0 means no update * @param _newPointsPerBlock update global points per block; 0 means no update */ function set(uint256 _pid, uint256 _emissionsMultiplier, uint256 _poolStartBlock, uint256 _newPointsPerBlock) external onlyOwner { if (isFarmingEnded()) { revert FarmingIsEnded(); } if (_newPointsPerBlock != 0) { setPointsPerBlock(_newPointsPerBlock); } else { massUpdatePools(); } PoolInfo storage pool = poolInfo[_pid]; address lpToken = address(pool.lpToken); if (lpToken == address(0) || !poolExists[lpToken]) { revert PoolDoesNotExist(); } if (_emissionsMultiplier != 0) { poolValue[_pid].emissionsMultiplier = _emissionsMultiplier; } // pool starting block is updated if farming hasn't started and _poolStartBlock is non-zero if (_poolStartBlock != 0 && getBlockNumber() < pool.lastRewardBlock) { pool.lastRewardBlock = getBlockNumber() > _poolStartBlock ? getBlockNumber() : _poolStartBlock; } emit Set(lpToken, _pid, 0); } /** * @notice Returns the number of pools in the farm * @return uint256 number of pools */ function poolLength() external view returns (uint256) { return poolInfo.length; } /** * @notice Checks if farming is ended * @return bool True if farming is ended */ function isFarmingEnded() public view returns (bool) { uint256 _endBlock = endBlock; return _endBlock != 0 && getBlockNumber() > _endBlock; } /** * @notice Checks if the withdrawal period is ended * @return bool True if withdrawal period is ended */ function isWithdrawPeriodEnded() public view returns (bool) { uint256 _endBlockForWithdrawals = endBlockForWithdrawals; return _endBlockForWithdrawals != 0 && getBlockNumber() > _endBlockForWithdrawals; } /** * @notice Set the end block of the farm * @param _endBlock the end block * @param _withdrawalBlocks the last block that withdrawals are allowed */ function setEndBlock(uint256 _endBlock, uint256 _withdrawalBlocks) external onlyOwner { if (isFarmingEnded()) { revert FarmingIsEnded(); } uint256 _endBlockForWithdrawals; if (_endBlock != 0) { if (getBlockNumber() > _endBlock) { revert InvalidEndBlock(); } _endBlockForWithdrawals = _endBlock + _withdrawalBlocks; } else { // withdrawal blocks needs an endBlock _endBlockForWithdrawals = 0; } massUpdatePools(); endBlock = _endBlock; endBlockForWithdrawals = _endBlockForWithdrawals; } /** * @notice Set points per block * @param _pointsPerBlock points per block to set */ function setPointsPerBlock(uint256 _pointsPerBlock) virtual public onlyOwner { if (isFarmingEnded()) { revert FarmingIsEnded(); } if (_pointsPerBlock < 1e18 || _pointsPerBlock > 1_000e18) { revert InvalidPointsPerBlock(); } massUpdatePools(); emit SetPointsPerBlock(pointsPerBlock, _pointsPerBlock); pointsPerBlock = _pointsPerBlock; } /** * @notice Returns the block multiplier * @param _from from block * @param _to to block * @return uint256 The block multiplier */ function _getBlockMultiplier(uint256 _from, uint256 _to) internal view returns (uint256) { uint256 _endBlock = endBlock; if (_endBlock != 0) { _to = Math.min(_to, _endBlock); } if (_to > _from) { return (_to - _from) * 1e18; } else { return 0; } } /** * @notice Adds or removes users from the whitelist * @param _userAdmin an admin user who can transfer points for users * @param _users list of users * @param _isInWhitelist to add or remove */ function setUsersWhitelisted(address _userAdmin, address[] memory _users, bool _isInWhitelist) external onlyOwner { mapping(address user => bool inWhitelist) storage whitelist_ = whitelist[_userAdmin]; for(uint i = 0; i < _users.length; i++) { whitelist_[_users[i]] = _isInWhitelist; } } /** * @notice Returns pending points for user in a pool * @param _pid pid of the pool * @param _user user in the pool * @return uint256 pendings points */ function _pendingPoints(uint256 _pid, address _user) internal view returns (uint256) { UserInfo storage user = userInfo[_pid][_user]; (uint256 accPointsPerShare, ) = _settlePool(_pid); return user.amount * accPointsPerShare / 1e18 + user.rewardSettled - user.rewardDebt; } /** * @notice Set emissions multiplier * @param _emissionsMultiplier emissions multiplier to set */ function setEmissionsMultiplier(uint256 _pid, uint256 _emissionsMultiplier) external onlyOwner { if (_emissionsMultiplier == 0) { // set multiplier to 1x _emissionsMultiplier = 1e18; } massUpdatePools(); PoolValue storage pv = poolValue[_pid]; emit SetEmissionsMultiplier(pv.emissionsMultiplier, _emissionsMultiplier); pv.emissionsMultiplier = _emissionsMultiplier; } /** * @notice Returns accPointsPerShare and totalRewards to date for the pool * @param _pid pid of the pool * @return accPointsPerShare * @return totalRewards */ function _settlePool(uint256 _pid) internal view returns (uint256 accPointsPerShare, uint256 totalRewards) { PoolInfo storage pool = poolInfo[_pid]; accPointsPerShare = pool.accPointsPerShare; totalRewards = pool.totalRewards; uint256 lpSupply = pool.amount; uint256 _totalValue = totalValue; if (getBlockNumber() > pool.lastRewardBlock && lpSupply != 0 && _totalValue != 0) { uint256 blockMultiplier = _getBlockMultiplier(pool.lastRewardBlock, getBlockNumber()); uint256 pointReward = blockMultiplier * pointsPerBlock * poolValue[_pid].lastValue / _totalValue; totalRewards = totalRewards + pointReward / 1e18; accPointsPerShare = pointReward / lpSupply + accPointsPerShare; } } /** * @notice Returns pending points for user in a pool * @param _pid pid of the pool * @param _user user in the pool * @return uint256 pendings points */ function pendingPoints(uint256 _pid, address _user) external view returns (uint256) { return _pendingPoints(_pid, _user); } /** * @notice Update accounting of all pools */ function massUpdatePools() public { uint256 length = poolInfo.length; uint256 totalNewValue; uint256 _pid; // [[lastRewardBlock, lastValue, lpSupply, newPrice]] uint256[4][] memory valuesArray = new uint256[4][](length); for(_pid = 0; _pid < length; ++_pid) { valuesArray[_pid] = _updatePool(_pid); totalNewValue += valuesArray[_pid][1]; } totalValue = totalNewValue; uint256 _pointsPerBlock = pointsPerBlock; for(_pid = 0; _pid < length; ++_pid) { uint256[4] memory values = valuesArray[_pid]; PoolInfo storage pool = poolInfo[_pid]; if (getBlockNumber() <= values[0]) { continue; } if (values[2] != 0 && values[1] != 0) { uint256 blockMultiplier = _getBlockMultiplier(values[0], getBlockNumber()); uint256 pointReward = blockMultiplier * _pointsPerBlock * values[1] / totalNewValue; pool.totalRewards = pool.totalRewards + pointReward / 1e18; pool.accPointsPerShare = pointReward / values[2] + pool.accPointsPerShare; } pool.lastRewardBlock = getBlockNumber(); emit PoolUpdated(_pid, values[1], values[3]); } } // returns [lastRewardBlock, lastValue, lpSupply, newPrice] function _updatePool(uint256 _pid) internal returns (uint256[4] memory values) { PoolInfo storage pool = poolInfo[_pid]; values[0] = pool.lastRewardBlock; if (getBlockNumber() < values[0]) { // pool doesn't start until a future block return values; } PoolValue storage pv = poolValue[_pid]; values[1] = pv.lastValue; if (getBlockNumber() == values[0]) { // pool was already processed this block, but we still need the value return values; } values[2] = pool.amount; if (values[2] == 0) { return values; } values[3] = priceFeeds.getPrice(address(pool.lpToken)); if (values[3] == 0) { // invalid price return values; } uint256 newValue = values[2] * values[3] / 1e18; newValue = newValue * pv.emissionsMultiplier / 1e18; if (newValue == 0) { // invalid value return values; } pv.lastValue = newValue; values[1] = newValue; return values; } /** * @notice Deposit assets to SophonFarming * @param _pid pid of the pool * @param _amount amount of the deposit * @param _boostAmount amount to boost */ function deposit(uint256 _pid, uint256 _amount, uint256 _boostAmount) external { poolInfo[_pid].lpToken.safeTransferFrom( msg.sender, address(this), _amount ); _deposit(_pid, _amount, _boostAmount); } /** * @notice Deposit an asset to SophonFarming * @param _pid pid of the deposit * @param _depositAmount amount of the deposit * @param _boostAmount amount to boost */ function _deposit(uint256 _pid, uint256 _depositAmount, uint256 _boostAmount) internal { if (isFarmingEnded()) { revert FarmingIsEnded(); } if (_depositAmount == 0) { revert InvalidDeposit(); } _boostAmount; // unused massUpdatePools(); PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; uint256 userAmount = user.amount; user.rewardSettled = userAmount * pool.accPointsPerShare / 1e18 + user.rewardSettled - user.rewardDebt; // set deposit amount user.depositAmount = user.depositAmount + _depositAmount; pool.depositAmount = pool.depositAmount + _depositAmount; userAmount = userAmount + _depositAmount; user.amount = userAmount; pool.amount = pool.amount + _depositAmount; user.rewardDebt = userAmount * pool.accPointsPerShare / 1e18; emit Deposit(msg.sender, _pid, _depositAmount, 0); } /** * @notice Returns max additional boost amount allowed to boost current deposits * @dev total allowed boost is 100% of total deposit * @param _user user in pool * @param _pid pid of pool * @return uint256 max additional boost */ function getMaxAdditionalBoost(address _user, uint256 _pid) public view returns (uint256) { return 0; } /** * @notice Withdraw an asset to SophonFarming * @param _pid pid of the withdraw * @param _withdrawAmount amount of the withdraw */ function withdraw(uint256 _pid, uint256 _withdrawAmount) external { if (isWithdrawPeriodEnded()) { revert WithdrawNotAllowed(); } if (_withdrawAmount == 0) { revert WithdrawIsZero(); } massUpdatePools(); PoolInfo storage pool = poolInfo[_pid]; UserInfo storage user = userInfo[_pid][msg.sender]; uint256 userDepositAmount = user.depositAmount; if (_withdrawAmount == type(uint256).max) { _withdrawAmount = userDepositAmount; } else if (_withdrawAmount > userDepositAmount) { revert WithdrawTooHigh(userDepositAmount); } uint256 userAmount = user.amount; user.rewardSettled = userAmount * pool.accPointsPerShare / 1e18 + user.rewardSettled - user.rewardDebt; user.depositAmount = userDepositAmount - _withdrawAmount; pool.depositAmount = pool.depositAmount - _withdrawAmount; userAmount = userAmount - _withdrawAmount; user.amount = userAmount; pool.amount = pool.amount - _withdrawAmount; user.rewardDebt = userAmount * pool.accPointsPerShare / 1e18; pool.lpToken.safeTransfer(msg.sender, _withdrawAmount); emit Withdraw(msg.sender, _pid, _withdrawAmount); } /** * @notice Called by an whitelisted admin to transfer points to another user * @param _pid pid of the pool to transfer points from * @param _sender address to send accrued points * @param _receiver address to receive accrued points * @param _transferAmount amount of points to transfer */ function transferPoints(uint256 _pid, address _sender, address _receiver, uint256 _transferAmount) external { if (!whitelist[msg.sender][_sender]) { revert TransferNotAllowed(); } if (_sender == _receiver || _receiver == address(this) || _transferAmount == 0) { revert InvalidTransfer(); } massUpdatePools(); PoolInfo storage pool = poolInfo[_pid]; if (address(pool.lpToken) == address(0)) { revert PoolDoesNotExist(); } uint256 accPointsPerShare = pool.accPointsPerShare; UserInfo storage userFrom = userInfo[_pid][_sender]; UserInfo storage userTo = userInfo[_pid][_receiver]; uint256 userFromAmount = userFrom.amount; uint256 userToAmount = userTo.amount; uint userFromRewardSettled = userFromAmount * accPointsPerShare / 1e18 + userFrom.rewardSettled - userFrom.rewardDebt; if (_transferAmount == type(uint256).max) { _transferAmount = userFromRewardSettled; } else if (_transferAmount > userFromRewardSettled) { revert TransferTooHigh(userFromRewardSettled); } userFrom.rewardSettled = userFromRewardSettled - _transferAmount; userTo.rewardSettled = userToAmount * accPointsPerShare / 1e18 + userTo.rewardSettled - userTo.rewardDebt + _transferAmount; userFrom.rewardDebt = userFromAmount * accPointsPerShare / 1e18; userTo.rewardDebt = userToAmount * accPointsPerShare / 1e18; emit TransferPoints(_sender, _receiver, _pid, _transferAmount); } function batchAwardPoints(uint256 _pid, address[] memory _receivers, uint256[] memory _quantities) external onlyOwner { if (_receivers.length != _quantities.length) { revert CountMismatch(); } PoolInfo storage pool = poolInfo[_pid]; if (address(pool.lpToken) == address(0)) { revert PoolDoesNotExist(); } uint256 _totalPoints; for (uint256 i; i < _receivers.length; i++) { UserInfo storage user = userInfo[_pid][_receivers[i]]; user.rewardSettled = user.rewardSettled + _quantities[i]; _totalPoints = _totalPoints + _quantities[i]; } pool.totalRewards = pool.totalRewards + _totalPoints; } /** * @notice Returns the current block number * @dev Included to help with testing since it can be overridden for custom functionality * @return uint256 current block number */ function getBlockNumber() virtual public view returns (uint256) { return block.number; } /** * @notice Returns info about each pool * @return poolInfos all pool info */ function getPoolInfo() external view returns (PoolInfo[] memory poolInfos) { uint256 length = poolInfo.length; poolInfos = new PoolInfo[](length); for(uint256 pid = 0; pid < length; ++pid) { poolInfos[pid] = poolInfo[pid]; (, poolInfos[pid].totalRewards) = _settlePool(pid); } } /** * @notice Returns user info for a list of users * @param _users list of users * @return userInfos optimized user info */ function getOptimizedUserInfo(address[] memory _users) external view returns (uint256[4][][] memory userInfos) { uint256 usersLen = _users.length; userInfos = new uint256[4][][](usersLen); uint256 poolLen = poolInfo.length; for(uint256 i = 0; i < usersLen; i++) { address _user = _users[i]; userInfos[i] = new uint256[4][](poolLen); for(uint256 pid = 0; pid < poolLen; ++pid) { UserInfo memory uinfo = userInfo[pid][_user]; userInfos[i][pid][0] = uinfo.amount; userInfos[i][pid][1] = uinfo.boostAmount; userInfos[i][pid][2] = uinfo.depositAmount; userInfos[i][pid][3] = _pendingPoints(pid, _user); } } } /** * @notice Returns accrued points for a list of users * @param _users list of users * @return pendings accured points for user */ function getPendingPoints(address[] memory _users) external view returns (uint256[][] memory pendings) { uint256 usersLen = _users.length; pendings = new uint256[][](usersLen); uint256 poolLen = poolInfo.length; for(uint256 i = 0; i < usersLen; i++) { address _user = _users[i]; pendings[i] = new uint256[](poolLen); for(uint256 pid = 0; pid < poolLen; ++pid) { pendings[i][pid] = _pendingPoints(pid, _user); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "contracts/token/ERC20/IERC20.sol"; import {IERC20Permit} from "contracts/token/ERC20/extensions/IERC20Permit.sol"; import {Address} from "contracts/utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "contracts/token/ERC20/IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.20; /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the Merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates Merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** *@dev The multiproof provided is not valid. */ error MerkleProofInvalidMultiproof(); /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a Merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all Merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. if (leavesLen + proofLen != totalHashes + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { if (proofPos != proofLen) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all Merkle trees admit multiproofs. See {processMultiProof} for details. */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the Merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. if (leavesLen + proofLen != totalHashes + 1) { revert MerkleProofInvalidMultiproof(); } // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { if (proofPos != proofLen) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Sorts the pair (a, b) and hashes the result. */ function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } /** * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. */ function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; interface IWeth { event Approval(address indexed src, address indexed guy, uint wad); event Transfer(address indexed src, address indexed dst, uint wad); event Deposit(address indexed dst, uint wad); event Withdrawal(address indexed src, uint wad); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function balanceOf(address user) external view returns (uint256); function allowance(address owner, address spender) external view returns (uint256); function totalSupply() external view returns (uint); function deposit() external payable; function withdraw(uint256 wad) external; function approve(address guy, uint wad) external returns (bool); function transfer(address dst, uint wad) external returns (bool); function transferFrom(address src, address dst, uint wad) external returns (bool); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; interface IstETH { function submit(address _referral) external payable returns (uint256); function getSharesByPooledEth(uint256 _ethAmount) external view returns (uint256); function getPooledEthByShares(uint256 _sharesAmount) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; interface IwstETH { function wrap(uint256 _stETHAmount) external returns (uint256); function unwrap(uint256 _wstETHAmount) external returns (uint256); function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256); function stEthPerToken() external view returns (uint256); function tokensPerStEth() external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; interface IsDAI { function deposit(uint256 assets, address receiver) external returns (uint256 shares); function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets); function convertToShares(uint256 assets) external view returns (uint256); function convertToAssets(uint256 shares) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; interface IeETHLiquidityPool { function deposit(address _referral) external payable returns (uint256); function sharesForAmount(uint256 _amount) external view returns (uint256); function amountForShare(uint256 _share) external view returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; interface IweETH { function wrap(uint256 _eETHAmount) external returns (uint256); }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; interface IPriceFeeds { event SetPriceFeedData(address indexed poolToken, FeedType feedType, bytes32 feedHash, uint256 staleSeconds); error ZeroAddress(); error CountMismatch(); error InvalidCall(); error InvalidType(); error TypeMismatch(); error InvalidStaleSeconds(); enum FeedType { Undefined, Stork } struct StorkData { bytes32 feedHash; uint256 staleSeconds; FeedType feedType; } function getPrice(address poolToken_) external view returns (uint256); function getStorkPrice(bytes32 feedHash_, uint256 staleSeconds_) external view returns (uint256); function setStorkFeedsData(address farmContract, address[] memory poolTokens_, StorkData[] memory poolTokenDatas_) external; }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; import "contracts/access/Ownable2Step.sol"; event ReplaceImplementationStarted(address indexed previousImplementation, address indexed newImplementation); event ReplaceImplementation(address indexed previousImplementation, address indexed newImplementation); error Unauthorized(); contract Upgradeable2Step is Ownable2Step { address public pendingImplementation; address public implementation; constructor() Ownable(msg.sender) {} // called on an inheriting proxy contract function replaceImplementation(address impl_) public onlyOwner { pendingImplementation = impl_; emit ReplaceImplementationStarted(implementation, impl_); } // called from an inheriting implementation contract function acceptImplementation() public { if (msg.sender != pendingImplementation) { revert OwnableUnauthorizedAccount(msg.sender); } emit ReplaceImplementation(implementation, msg.sender); delete pendingImplementation; implementation = msg.sender; } // called on an inheriting implementation contract function becomeImplementation(Upgradeable2Step proxy) public { if (msg.sender != proxy.owner()) { revert Unauthorized(); } proxy.acceptImplementation(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "contracts/access/Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "contracts/utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: GPL-3.0-only pragma solidity 0.8.26; import "contracts/token/ERC20/IERC20.sol"; import "contracts/farm/interfaces/bridge/IBridgehub.sol"; contract SophonFarmingState { // Info of each pool. struct PoolInfo { IERC20 lpToken; // Address of LP token contract. address l2Farm; // Address of the farming contract on Sophon chain uint256 amount; // total amount of LP tokens earning yield from deposits and boosts uint256 boostAmount; // total boosted value purchased by users uint256 depositAmount; // remaining deposits not applied to a boost purchases uint256 allocPoint; // How many allocation points assigned to this pool. Points to distribute per block. uint256 lastRewardBlock; // Last block number that points distribution occurs. uint256 accPointsPerShare; // Accumulated points per share. uint256 totalRewards; // Total rewards earned by the pool. string description; // Description of pool. } // Info of each user. struct UserInfo { uint256 amount; // Amount of LP tokens the user is earning yield on from deposits and boosts uint256 boostAmount; // Boosted value purchased by the user uint256 depositAmount; // remaining deposits not applied to a boost purchases uint256 rewardSettled; // rewards settled uint256 rewardDebt; // rewards debt } enum PredefinedPool { sDAI, // MakerDAO (sDAI) wstETH, // Lido (wstETH) weETH // ether.fi (weETH) } mapping(PredefinedPool => uint256) public typeToId; // held proceeds from booster sales mapping(uint256 => uint256) public heldProceeds; uint256 public boosterMultiplier; // Points created per block. uint256 public pointsPerBlock; // Info of each pool. PoolInfo[] public poolInfo; // Info of each user that stakes LP tokens. mapping(uint256 => mapping(address => UserInfo)) public userInfo; // Total allocation points. Must be the sum of all allocation points in all pools. uint256 public totalAllocPoint; // The block number when point mining ends. uint256 public endBlock; bool internal _initialized; mapping(address => bool) public poolExists; uint256 public endBlockForWithdrawals; IBridgehub public bridge; mapping(uint256 => bool) public isBridged; mapping(address userAdmin => mapping(address user => bool inWhitelist)) public whitelist; struct PoolValue { uint256 lastValue; uint256 emissionsMultiplier; } mapping(uint256 pid => PoolValue) public poolValue; // total USD value of all pools including all deposits, boosts, and emissionsMultipliers uint256 public totalValue; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {IL1SharedBridge} from "contracts/farm/interfaces/bridge/IL1SharedBridge.sol"; import {L2Message, L2Log, TxStatus} from "contracts/farm/interfaces/bridge/Messaging.sol"; struct L2TransactionRequestDirect { uint256 chainId; uint256 mintValue; address l2Contract; uint256 l2Value; bytes l2Calldata; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; bytes[] factoryDeps; address refundRecipient; } struct L2TransactionRequestTwoBridgesOuter { uint256 chainId; uint256 mintValue; uint256 l2Value; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; address refundRecipient; address secondBridgeAddress; uint256 secondBridgeValue; bytes secondBridgeCalldata; } struct L2TransactionRequestTwoBridgesInner { bytes32 magicValue; address l2Contract; bytes l2Calldata; bytes[] factoryDeps; bytes32 txDataHash; } interface IBridgehub { /// @notice pendingAdmin is changed /// @dev Also emitted when new admin is accepted and in this case, `newPendingAdmin` would be zero address event NewPendingAdmin(address indexed oldPendingAdmin, address indexed newPendingAdmin); /// @notice Admin changed event NewAdmin(address indexed oldAdmin, address indexed newAdmin); /// @notice Starts the transfer of admin rights. Only the current admin can propose a new pending one. /// @notice New admin can accept admin rights by calling `acceptAdmin` function. /// @param _newPendingAdmin Address of the new admin function setPendingAdmin(address _newPendingAdmin) external; /// @notice Accepts transfer of admin rights. Only pending admin can accept the role. function acceptAdmin() external; /// Getters function stateTransitionManagerIsRegistered(address _stateTransitionManager) external view returns (bool); function stateTransitionManager(uint256 _chainId) external view returns (address); function tokenIsRegistered(address _baseToken) external view returns (bool); function baseToken(uint256 _chainId) external view returns (address); function sharedBridge() external view returns (IL1SharedBridge); function getHyperchain(uint256 _chainId) external view returns (address); /// Mailbox forwarder function proveL2MessageInclusion( uint256 _chainId, uint256 _batchNumber, uint256 _index, L2Message calldata _message, bytes32[] calldata _proof ) external view returns (bool); function proveL2LogInclusion( uint256 _chainId, uint256 _batchNumber, uint256 _index, L2Log memory _log, bytes32[] calldata _proof ) external view returns (bool); function proveL1ToL2TransactionStatus( uint256 _chainId, bytes32 _l2TxHash, uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes32[] calldata _merkleProof, TxStatus _status ) external view returns (bool); function requestL2TransactionDirect( L2TransactionRequestDirect calldata _request ) external payable returns (bytes32 canonicalTxHash); function requestL2TransactionTwoBridges( L2TransactionRequestTwoBridgesOuter calldata _request ) external payable returns (bytes32 canonicalTxHash); function l2TransactionBaseCost( uint256 _chainId, uint256 _gasPrice, uint256 _l2GasLimit, uint256 _l2GasPerPubdataByteLimit ) external view returns (uint256); //// Registry function createNewChain( uint256 _chainId, address _stateTransitionManager, address _baseToken, uint256 _salt, address _admin, bytes calldata _initData ) external returns (uint256 chainId); function addStateTransitionManager(address _stateTransitionManager) external; function removeStateTransitionManager(address _stateTransitionManager) external; function addToken(address _token) external; function setSharedBridge(address _sharedBridge) external; event NewChain(uint256 indexed chainId, address stateTransitionManager, address indexed chainGovernance); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; /// @title L1 Bridge contract interface /// @author Matter Labs /// @custom:security-contact [email protected] interface IL1SharedBridge { event LegacyDepositInitiated( uint256 indexed chainId, bytes32 indexed l2DepositTxHash, address indexed from, address to, address l1Token, uint256 amount ); event BridgehubDepositInitiated( uint256 indexed chainId, bytes32 indexed txDataHash, address indexed from, address to, address l1Token, uint256 amount ); event BridgehubDepositBaseTokenInitiated( uint256 indexed chainId, address indexed from, address l1Token, uint256 amount ); event BridgehubDepositFinalized( uint256 indexed chainId, bytes32 indexed txDataHash, bytes32 indexed l2DepositTxHash ); event WithdrawalFinalizedSharedBridge( uint256 indexed chainId, address indexed to, address indexed l1Token, uint256 amount ); event ClaimedFailedDepositSharedBridge( uint256 indexed chainId, address indexed to, address indexed l1Token, uint256 amount ); function isWithdrawalFinalized( uint256 _chainId, uint256 _l2BatchNumber, uint256 _l2MessageIndex ) external view returns (bool); function depositLegacyErc20Bridge( address _msgSender, address _l2Receiver, address _l1Token, uint256 _amount, uint256 _l2TxGasLimit, uint256 _l2TxGasPerPubdataByte, address _refundRecipient ) external payable returns (bytes32 txHash); function claimFailedDepositLegacyErc20Bridge( address _depositSender, address _l1Token, uint256 _amount, bytes32 _l2TxHash, uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes32[] calldata _merkleProof ) external; function claimFailedDeposit( uint256 _chainId, address _depositSender, address _l1Token, uint256 _amount, bytes32 _l2TxHash, uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes32[] calldata _merkleProof ) external; function finalizeWithdrawalLegacyErc20Bridge( uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes calldata _message, bytes32[] calldata _merkleProof ) external returns (address l1Receiver, address l1Token, uint256 amount); function finalizeWithdrawal( uint256 _chainId, uint256 _l2BatchNumber, uint256 _l2MessageIndex, uint16 _l2TxNumberInBatch, bytes calldata _message, bytes32[] calldata _merkleProof ) external; function setEraPostDiamondUpgradeFirstBatch(uint256 _eraPostDiamondUpgradeFirstBatch) external; function setEraPostLegacyBridgeUpgradeFirstBatch(uint256 _eraPostLegacyBridgeUpgradeFirstBatch) external; function setEraLegacyBridgeLastDepositTime( uint256 _eraLegacyBridgeLastDepositBatch, uint256 _eraLegacyBridgeLastDepositTxNumber ) external; function L1_WETH_TOKEN() external view returns (address); function BRIDGE_HUB() external view returns (address); function legacyBridge() external view returns (address); function l2BridgeAddress(uint256 _chainId) external view returns (address); function depositHappened(uint256 _chainId, bytes32 _l2TxHash) external view returns (bytes32); struct L2TransactionRequestTwoBridgesInner { bytes32 magicValue; address l2Contract; bytes l2Calldata; bytes[] factoryDeps; bytes32 txDataHash; } /// data is abi encoded : /// address _l1Token, /// uint256 _amount, /// address _l2Receiver function bridgehubDeposit( uint256 _chainId, address _prevMsgSender, uint256 _l2Value, bytes calldata _data ) external payable returns (L2TransactionRequestTwoBridgesInner memory request); function bridgehubDepositBaseToken( uint256 _chainId, address _prevMsgSender, address _l1Token, uint256 _amount ) external payable; function bridgehubConfirmL2Transaction(uint256 _chainId, bytes32 _txDataHash, bytes32 _txHash) external; function receiveEth(uint256 _chainId) external payable; }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; /// @dev The enum that represents the transaction execution status /// @param Failure The transaction execution failed /// @param Success The transaction execution succeeded enum TxStatus { Failure, Success } /// @dev The log passed from L2 /// @param l2ShardId The shard identifier, 0 - rollup, 1 - porter /// All other values are not used but are reserved for the future /// @param isService A boolean flag that is part of the log along with `key`, `value`, and `sender` address. /// This field is required formally but does not have any special meaning /// @param txNumberInBatch The L2 transaction number in a Batch, in which the log was sent /// @param sender The L2 address which sent the log /// @param key The 32 bytes of information that was sent in the log /// @param value The 32 bytes of information that was sent in the log // Both `key` and `value` are arbitrary 32-bytes selected by the log sender struct L2Log { uint8 l2ShardId; bool isService; uint16 txNumberInBatch; address sender; bytes32 key; bytes32 value; } /// @dev An arbitrary length message passed from L2 /// @notice Under the hood it is `L2Log` sent from the special system L2 contract /// @param txNumberInBatch The L2 transaction number in a Batch, in which the message was sent /// @param sender The address of the L2 account from which the message was passed /// @param data An arbitrary length message struct L2Message { uint16 txNumberInBatch; address sender; bytes data; } /// @dev Internal structure that contains the parameters for the writePriorityOp /// internal function. /// @param txId The id of the priority transaction. /// @param l2GasPrice The gas price for the l2 priority operation. /// @param expirationTimestamp The timestamp by which the priority operation must be processed by the operator. /// @param request The external calldata request for the priority operation. struct WritePriorityOpParams { uint256 txId; uint256 l2GasPrice; uint64 expirationTimestamp; BridgehubL2TransactionRequest request; } /// @dev Structure that includes all fields of the L2 transaction /// @dev The hash of this structure is the "canonical L2 transaction hash" and can /// be used as a unique identifier of a tx /// @param txType The tx type number, depending on which the L2 transaction can be /// interpreted differently /// @param from The sender's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param to The recipient's address. `uint256` type for possible address format changes /// and maintaining backward compatibility /// @param gasLimit The L2 gas limit for L2 transaction. Analog to the `gasLimit` on an /// L1 transactions /// @param gasPerPubdataByteLimit Maximum number of L2 gas that will cost one byte of pubdata /// (every piece of data that will be stored on L1 as calldata) /// @param maxFeePerGas The absolute maximum sender willing to pay per unit of L2 gas to get /// the transaction included in a Batch. Analog to the EIP-1559 `maxFeePerGas` on an L1 transactions /// @param maxPriorityFeePerGas The additional fee that is paid directly to the validator /// to incentivize them to include the transaction in a Batch. Analog to the EIP-1559 /// `maxPriorityFeePerGas` on an L1 transactions /// @param paymaster The address of the EIP-4337 paymaster, that will pay fees for the /// transaction. `uint256` type for possible address format changes and maintaining backward compatibility /// @param nonce The nonce of the transaction. For L1->L2 transactions it is the priority /// operation Id /// @param value The value to pass with the transaction /// @param reserved The fixed-length fields for usage in a future extension of transaction /// formats /// @param data The calldata that is transmitted for the transaction call /// @param signature An abstract set of bytes that are used for transaction authorization /// @param factoryDeps The set of L2 bytecode hashes whose preimages were shown on L1 /// @param paymasterInput The arbitrary-length data that is used as a calldata to the paymaster pre-call /// @param reservedDynamic The arbitrary-length field for usage in a future extension of transaction formats struct L2CanonicalTransaction { uint256 txType; uint256 from; uint256 to; uint256 gasLimit; uint256 gasPerPubdataByteLimit; uint256 maxFeePerGas; uint256 maxPriorityFeePerGas; uint256 paymaster; uint256 nonce; uint256 value; // In the future, we might want to add some // new fields to the struct. The `txData` struct // is to be passed to account and any changes to its structure // would mean a breaking change to these accounts. To prevent this, // we should keep some fields as "reserved" // It is also recommended that their length is fixed, since // it would allow easier proof integration (in case we will need // some special circuit for preprocessing transactions) uint256[4] reserved; bytes data; bytes signature; uint256[] factoryDeps; bytes paymasterInput; // Reserved dynamic type for the future use-case. Using it should be avoided, // But it is still here, just in case we want to enable some additional functionality bytes reservedDynamic; } /// @param sender The sender's address. /// @param contractAddressL2 The address of the contract on L2 to call. /// @param valueToMint The amount of base token that should be minted on L2 as the result of this transaction. /// @param l2Value The msg.value of the L2 transaction. /// @param l2Calldata The calldata for the L2 transaction. /// @param l2GasLimit The limit of the L2 gas for the L2 transaction /// @param l2GasPerPubdataByteLimit The price for a single pubdata byte in L2 gas. /// @param factoryDeps The array of L2 bytecodes that the tx depends on. /// @param refundRecipient The recipient of the refund for the transaction on L2. If the transaction fails, then /// this address will receive the `l2Value`. struct BridgehubL2TransactionRequest { address sender; address contractL2; uint256 mintValue; uint256 l2Value; bytes l2Calldata; uint256 l2GasLimit; uint256 l2GasPerPubdataByteLimit; bytes[] factoryDeps; address refundRecipient; }
{ "evmVersion": "shanghai", "optimizer": { "enabled": true, "runs": 200 }, "libraries": { "SophonFarmingL2.sol": {} }, "remappings": [ "@erc721a=./node_modules/erc721a/contracts", "@chainlink=./node_modules/@chainlink/contracts/src/v0.8", "@openzeppelin=./node_modules/@openzeppelin", "OpenZeppelin=C:/Users/tomcb/.brownie/packages/OpenZeppelin", "paulrberg=C:/Users/tomcb/.brownie/packages/paulrberg" ], "metadata": { "appendCBOR": false, "bytecodeHash": "none" }, "outputSelection": { "*": { "*": [ "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_MERKLE","type":"address"},{"internalType":"address","name":"_priceFeeds","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"BridgeInvalid","type":"error"},{"inputs":[],"name":"CountMismatch","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"FarmingIsEnded","type":"error"},{"inputs":[],"name":"FarmingIsStarted","type":"error"},{"inputs":[],"name":"InvalidDeposit","type":"error"},{"inputs":[],"name":"InvalidEndBlock","type":"error"},{"inputs":[],"name":"InvalidPointsPerBlock","type":"error"},{"inputs":[],"name":"InvalidTransfer","type":"error"},{"inputs":[],"name":"NoEthSent","type":"error"},{"inputs":[{"internalType":"address","name":"lpToken","type":"address"}],"name":"NotFound","type":"error"},{"inputs":[],"name":"NothingInPool","type":"error"},{"inputs":[],"name":"OnlyMerkle","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PoolDoesNotExist","type":"error"},{"inputs":[],"name":"PoolExists","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TransferNotAllowed","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxAllowed","type":"uint256"}],"name":"TransferTooHigh","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"WithdrawIsZero","type":"error"},{"inputs":[],"name":"WithdrawNotAllowed","type":"error"},{"inputs":[{"internalType":"uint256","name":"maxAllowed","type":"uint256"}],"name":"WithdrawTooHigh","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lpToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"}],"name":"Add","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boostAmount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"boostAmount","type":"uint256"}],"name":"IncreaseBoost","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"currentValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newPrice","type":"uint256"}],"name":"PoolUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"ReplaceImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousImplementation","type":"address"},{"indexed":true,"internalType":"address","name":"newImplementation","type":"address"}],"name":"ReplaceImplementationStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"lpToken","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"allocPoint","type":"uint256"}],"name":"Set","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"SetEmissionsMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newValue","type":"uint256"}],"name":"SetPointsPerBlock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferPoints","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pid","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawHeldProceeds","type":"event"},{"inputs":[],"name":"MERKLE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_lpToken","type":"address"},{"internalType":"uint256","name":"_emissionsMultiplier","type":"uint256"},{"internalType":"string","name":"_description","type":"string"},{"internalType":"uint256","name":"_poolStartBlock","type":"uint256"},{"internalType":"uint256","name":"_newPointsPerBlock","type":"uint256"}],"name":"add","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address[]","name":"_receivers","type":"address[]"},{"internalType":"uint256[]","name":"_quantities","type":"uint256[]"}],"name":"batchAwardPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Upgradeable2Step","name":"proxy","type":"address"}],"name":"becomeImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"boosterMultiplier","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridge","outputs":[{"internalType":"contract IBridgehub","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_boostAmount","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"endBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"endBlockForWithdrawals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBlockNumber","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"}],"name":"getMaxAdditionalBoost","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"getOptimizedUserInfo","outputs":[{"internalType":"uint256[4][][]","name":"userInfos","type":"uint256[4][][]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_users","type":"address[]"}],"name":"getPendingPoints","outputs":[{"internalType":"uint256[][]","name":"pendings","type":"uint256[][]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolInfo","outputs":[{"components":[{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"address","name":"l2Farm","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"boostAmount","type":"uint256"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accPointsPerShare","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"string","name":"description","type":"string"}],"internalType":"struct SophonFarmingState.PoolInfo[]","name":"poolInfos","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"heldProceeds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"implementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isBridged","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFarmingEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isWithdrawPeriodEnded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"massUpdatePools","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"pendingPoints","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pointsPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"poolExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolInfo","outputs":[{"internalType":"contract IERC20","name":"lpToken","type":"address"},{"internalType":"address","name":"l2Farm","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"boostAmount","type":"uint256"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"allocPoint","type":"uint256"},{"internalType":"uint256","name":"lastRewardBlock","type":"uint256"},{"internalType":"uint256","name":"accPointsPerShare","type":"uint256"},{"internalType":"uint256","name":"totalRewards","type":"uint256"},{"internalType":"string","name":"description","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pid","type":"uint256"}],"name":"poolValue","outputs":[{"internalType":"uint256","name":"lastValue","type":"uint256"},{"internalType":"uint256","name":"emissionsMultiplier","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceFeeds","outputs":[{"internalType":"contract IPriceFeeds","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"impl_","type":"address"}],"name":"replaceImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_emissionsMultiplier","type":"uint256"},{"internalType":"uint256","name":"_poolStartBlock","type":"uint256"},{"internalType":"uint256","name":"_newPointsPerBlock","type":"uint256"}],"name":"set","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_emissionsMultiplier","type":"uint256"}],"name":"setEmissionsMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_endBlock","type":"uint256"},{"internalType":"uint256","name":"_withdrawalBlocks","type":"uint256"}],"name":"setEndBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pointsPerBlock","type":"uint256"}],"name":"setPointsPerBlock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_userAdmin","type":"address"},{"internalType":"address[]","name":"_users","type":"address[]"},{"internalType":"bool","name":"_isInWhitelist","type":"bool"}],"name":"setUsersWhitelisted","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalAllocPoint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalValue","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_transferAmount","type":"uint256"}],"name":"transferPoints","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum SophonFarmingState.PredefinedPool","name":"","type":"uint8"}],"name":"typeToId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"},{"internalType":"uint256","name":"_pid","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"boostAmount","type":"uint256"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"rewardSettled","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"internalType":"struct SophonFarmingState.UserInfo","name":"_userFromClaim","type":"tuple"}],"name":"updateUserInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"userInfo","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"boostAmount","type":"uint256"},{"internalType":"uint256","name":"depositAmount","type":"uint256"},{"internalType":"uint256","name":"rewardSettled","type":"uint256"},{"internalType":"uint256","name":"rewardDebt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"userAdmin","type":"address"},{"internalType":"address","name":"user","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"inWhitelist","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"uint256","name":"_withdrawAmount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pid","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawHeldProceeds","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
9c4d535b0000000000000000000000000000000000000000000000000000000000000000010005d9c692d48e10ff1bbdaaa2dd5363170ea16a0b7d5f306e4ea7786105fe00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000040000000000000000000000000a24f69faa295426bca2cf610bf992cdc992ceea00000000000000000000000002edf18b640a705f16947a7b95fc338fde340dd48
Deployed Bytecode
0x000400000000000200160000000000020000006004100270000005390340019700030000003103550002000000010355000005390040019d0000000100200190000000390000c13d0000008004000039000000400040043f000000040030008c000000600000413d000000000201043b000000e002200270000005430020009c000000620000a13d000005440020009c000000730000a13d000005450020009c000000a60000a13d000005460020009c0000016a0000a13d000005470020009c000003160000213d0000054a0020009c0000037f0000613d0000054b0020009c000000600000c13d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000601043b0000053c0060009c000000600000213d000000000100041a0000053c011001970000000005000411000000000051004b000007ca0000c13d0000000101000039000000000201041a0000053d02200197000000000262019f000000000021041b0000000001000414000005390010009c0000053901008041000000c0011002100000053e011001c70000800d0200003900000003030000390000059304000041000006da0000013d0000000002000416000000000002004b000000600000c13d0000001f023000390000053a02200197000000c002200039000000400020043f0000001f0430018f0000053b05300198000000c0025000390000004a0000613d000000c006000039000000000701034f000000007807043c0000000006860436000000000026004b000000460000c13d000000000004004b000000570000613d000000000151034f0000000304400210000000000502043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f0000000000120435000000400030008c000000600000413d000000c00100043d0000053c0010009c000000600000213d000000e00200043d001100000002001d0000053c0020009c0000009e0000a13d0000000001000019000014e000010430000005650020009c000000870000213d000005750020009c000000b30000213d0000057d0020009c000001750000213d000005810020009c000003940000613d000005820020009c000003c30000613d000005830020009c000000600000c13d0000000001000416000000000001004b000000600000c13d0000000b01000039000007850000013d000005560020009c000000c70000213d0000055e0020009c0000019f0000213d000005620020009c000003c80000613d000005630020009c000003d60000613d000005640020009c000000600000c13d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b000000000010043f0000000501000039000001f70000013d000005660020009c000000da0000213d0000056e0020009c000001af0000213d000005720020009c000003ef0000613d000005730020009c000003f40000613d000005740020009c000000600000c13d0000000001000416000000000001004b000000600000c13d0000800b0100003900000004030000390000000004000415000000160440008a00000005044002100000058d0200004114de14b60000040f000000800010043f0000059b01000041000014df0001042e0000000006000411000000000006004b0000014b0000c13d0000054101000041000000000010043f000000040000043f0000054201000041000014e0000104300000054f0020009c000001db0000213d000005530020009c000003f90000613d000005540020009c000004180000613d000005550020009c000000600000c13d0000000001000416000000000001004b000000600000c13d0000000e01000039000007850000013d000005760020009c000001e60000213d0000057a0020009c000004420000613d0000057b0020009c000004470000613d0000057c0020009c000000600000c13d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b0000053c0010009c000000600000213d000000000010043f0000000d010000390000040e0000013d000005570020009c000001fb0000213d0000055b0020009c000004710000613d0000055c0020009c000004970000613d0000055d0020009c000000600000c13d0000000001000416000000000001004b000000600000c13d0000000001000412001300000001001d001200000000003d000080050100003900000044030000390000000004000415000000130440008a000003d20000013d000005670020009c000002f80000213d0000056b0020009c000004e90000613d0000056c0020009c000005140000613d0000056d0020009c000000600000c13d000000640030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b0000053c0020009c000000600000213d0000002404100370000000000404043b000005840040009c000000600000213d0000002305400039000000000035004b000000600000813d0000000405400039000000000551034f000000000605043b000005840060009c0000098c0000213d00000005056002100000003f075000390000058507700197000005860070009c0000098c0000213d0000008007700039000000400070043f000000800060043f00000024044000390000000005450019000000000035004b000000600000213d000000000006004b0000010f0000613d0000008003000039000000000641034f000000000606043b0000053c0060009c000000600000213d000000200330003900000000006304350000002004400039000000000054004b000001060000413d0000004401100370000000000301043b000000000003004b0000000001000039000000010100c039001000000003001d000000000013004b000000600000c13d000000000100041a0000053c031001970000000001000411000000000013004b000007b90000c13d0000053c01200197000000000010043f0000001101000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000f00000001001d000000800100043d000000000001004b000006dd0000613d0000000004000019001100000004001d0000000501400210000000a00110003900000000010104330000053c01100197000000000010043f0000000f01000029000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f00000011040000290000000100200190000000600000613d000000000101043b000000000201041a000005cd0220019700000010022001af000000000021041b0000000104400039000000800100043d000000000014004b0000012f0000413d000006dd0000013d001000000001001d0000000101000039000000000201041a0000053d02200197000000000021041b000000000100041a0000053d02100197000000000262019f000000000020041b00000000020004140000053c05100197000005390020009c0000053902008041000000c0012002100000053e011001c70000800d0200003900000003030000390000053f0400004114de14d40000040f00000010010000290000000100200190000000600000613d000000000001004b000001660000613d000000800010043f000000110000006b000007be0000c13d000005b101000041000000000010043f0000059701000041000014e0000104300000054c0020009c0000051a0000613d0000054d0020009c000005ac0000613d0000054e0020009c000000600000c13d0000000001000416000000000001004b000000600000c13d0000000f01000039000006b30000013d0000057e0020009c000005b10000613d0000057f0020009c000005bf0000613d000005800020009c000000600000c13d0000000001000416000000000001004b000000600000c13d0000000201000039000000000201041a0000053c012001970000000006000411000000000016004b000009660000c13d001100000002001d0000000303000039000000000203041a0000000001000414000005390010009c0000053901008041000000c0011002100000053e011001c7001000000002001d0000053c052001970000800d02000039000005c80400004114de14d40000040f0000000100200190000000600000613d00000011010000290000053d011001970000000202000039000000000012041b00000010010000290000053d011001970000000002000411000000000121019f0000000302000039000000000012041b0000000001000019000014df0001042e0000055f0020009c000006140000613d000005600020009c000006960000613d000005610020009c000000600000c13d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b000000000010043f00000010010000390000040e0000013d0000056f0020009c0000069b0000613d000005700020009c000006af0000613d000005710020009c000000600000c13d0000000001000416000000000001004b000000600000c13d0000000801000039000000000101041a000a00000001001d000005ba0010009c0000098c0000813d0000000a0100002900000005021002100000003f012000390000058503100197000005860030009c0000098c0000213d0000008001300039000000400010043f0000000a04000029000000800040043f000000000004004b0000096b0000c13d00000020020000390000000003210436000000800200043d0000000000230435000000400310003900000005042002100000000008340019000000000002004b000009b40000c13d0000000002180049000005390020009c00000539020080410000006002200210000005390010009c00000539010080410000004001100210000000000112019f000014df0001042e000005500020009c000006b80000613d000005510020009c000006bd0000613d000005520020009c000000600000c13d0000000001000416000000000001004b000000600000c13d14de12a50000040f000005b50000013d000005770020009c000006df0000613d000005780020009c000007160000613d000005790020009c000000600000c13d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b000000020010008c000000600000213d000000000010043f0000000401000039000000200010043f000000400100003914de14a50000040f000007850000013d000005580020009c000007550000613d000005590020009c000007680000613d0000055a0020009c000000600000c13d000000a40030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b001100000002001d0000053c0020009c000000600000213d0000002402100370000000000202043b001000000002001d0000004402100370000000000402043b000005840040009c000000600000213d0000002302400039000000000032004b000000600000813d0000000405400039000000000251034f000000000202043b000005840020009c0000098c0000213d0000001f06200039000005ce066001970000003f06600039000005ce06600197000005860060009c0000098c0000213d0000008006600039000000400060043f000000800020043f00000000042400190000002404400039000000000034004b000000600000213d0000002003500039000000000431034f000005ce052001980000001f0620018f000000a003500039000002330000613d000000a007000039000000000804034f000000008908043c0000000007970436000000000037004b0000022f0000c13d000000000006004b000002400000613d000000000454034f0000000305600210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000430435000000a00220003900000000000204350000008402100370000000000202043b000f00000002001d0000006401100370000000000101043b000e00000001001d000000000100041a0000053c011001970000000002000411000000000021004b00000f0b0000c13d000000110000006b000001660000613d0000001101000029000000000010043f0000000d01000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000000000101041a000000ff0010019000000ed60000c13d0000000b01000039000000000101041a000d00000001001d000000000001004b000002730000613d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000d0010006c000008c20000213d0000000f0000006b00000ede0000c13d14de10cc0000040f0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b000f00000001001d0000001101000029000000000010043f0000000d01000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000f040000290000000e0040006c0000000e0400a0290000000100200190000000600000613d000000000101043b000000000201041a000005cd0220019700000001022001bf000000000021041b000000400600043d000005aa0060009c0000098c0000213d0000000809000039000000000c09041a0000014001600039000000400010043f000001200160003900000080020000390000000000210435000000c00360003900000000004304350000001102000029000000000a26043600000100026000390000000000020435000000e0046000390000000000040435000000a00560003900000000000504350000008007600039000000000007043500000060086000390000000000080435000000400b60003900000000000b043500000000000a0435000f0000000c001d0000058400c0009c0000098c0000213d0000000f0d000029000000010cd000390000000000c9041b000000000090043f00000000060604330000053c096001970000000a06d000c9000005a50c60009a000000000d0c041a0000053d0dd0019700000000099d019f00000000009c041b00000000090a04330000053c09900197000005ab0a60009a000000000c0a041a0000053d0cc0019700000000099c019f00000000009a041b00000000090b04330000058a0a60009a00000000009a041b0000000008080433000005ac0960009a000000000089041b0000000007070433000005ad0860009a000000000078041b0000000005050433000005ae0760009a000000000057041b0000000003030433000005890560009a000000000035041b00000000030404330000058c0460009a000000000034041b00000000020204330000058b0360009a000000000023041b0000000001010433000d00000001001d0000000021010434000c00000002001d000e00000001001d000005840010009c0000098c0000213d000005af0160009a000b00000001001d000000000101041a000000010010019000000001021002700000007f0220618f000a00000002001d0000001f0020008c00000000020000390000000102002039000000000121013f000000010010019000000f9a0000613d000005bc01000041000000000010043f0000002201000039000000040010043f0000054201000041000014e000010430000005680020009c000007750000613d000005690020009c000007810000613d0000056a0020009c000000600000c13d0000000001000416000000000001004b000000600000c13d000000000100041a0000053c021001970000000005000411000000000052004b000007ca0000c13d0000000102000039000000000302041a0000053d03300197000000000032041b0000053d01100197000000000010041b0000000001000414000005390010009c0000053901008041000000c0011002100000053e011001c70000800d0200003900000003030000390000053f040000410000000006000019000006da0000013d000005480020009c000007890000613d000005490020009c000000600000c13d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b000005840020009c000000600000213d0000002305200039000000000035004b000000600000813d0000000405200039000000000551034f000000000605043b000005840060009c0000098c0000213d00000005056002100000003f075000390000058507700197000005860070009c0000098c0000213d0000008007700039000800000007001d000000400070043f000000800060043f00000024022000390000000005250019000000000035004b000000600000213d000000000006004b00000000030000190000034b0000613d000000000321034f000000000303043b0000053c0030009c000000600000213d000000200440003900000000003404350000002002200039000000000052004b0000033b0000413d000000800100043d000005840010009c0000098c0000213d0000000002010019000000400100043d000800000001001d0000000003020019000300000003001d00000005013002100000003f0210003900000587032001970000000802300029000000000032004b00000000030000390000000103004039000005840020009c0000098c0000213d00000001003001900000098c0000c13d000000400020043f000000080200002900000003030000290000000005320436000000000003004b000b00000005001d00000c5a0000c13d000000400100043d00000020020000390000000002210436000000080300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b000004e70000613d00000000050000190000000b0a0000290000036f0000013d0000000105500039000000000035004b000004e70000813d0000000006120049000000400660008a000000000464043600000000a60a043400000000070604330000000002720436000000000007004b0000036c0000613d00000000080000190000002006600039000000000906043300000000029204360000000108800039000000000078004b000003780000413d0000036c0000013d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b0000053c0010009c000000600000213d0000053c021001970000059401000041000000800010043f0000000001000414000000040020008c001100000002001d0000081c0000c13d0000000103000031000000200030008c00000020040000390000000004034019000008410000013d000000640030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000002402100370000000000202043b001100000002001d0000000401100370000000000201043b0000000801000039000000000101041a001000000002001d000000000021004b00000d5a0000a13d0000000801000039000000000010043f00000010010000290000000a011000c9000f00000001001d000005a50110009a000000000101041a000005c902000041000000a00020043f0000000002000411000000a40020043f0000000002000410000000c40020043f0000001102000029000000e40020043f0000006402000039000000800020043f0000012002000039000000400020043f0000053c01100197000000800200003914de140c0000040f0000000b01000039000000000101041a000000000001004b0000087a0000c13d000000110000006b000008c60000c13d000005cc01000041000000000010043f0000059701000041000014e0000104300000000001000416000000000001004b000000600000c13d0000000801000039000007850000013d0000000001000416000000000001004b000000600000c13d0000000001000412001500000001001d001400200000003d000080050100003900000044030000390000000004000415000000150440008a00000005044002100000059c0200004114de14b60000040f000006b40000013d0000000001000416000000000001004b000000600000c13d0000000101000039000000000201041a0000053c032001970000000006000411000000000063004b000009660000c13d0000053d02200197000000000021041b000000000100041a0000053d02100197000000000262019f000000000020041b00000000020004140000053c05100197000005390020009c0000053902008041000000c0012002100000053e011001c70000800d0200003900000003030000390000053f04000041000006da0000013d0000000001000416000000000001004b000000600000c13d0000000201000039000006b30000013d0000000001000416000000000001004b000000600000c13d0000000701000039000007850000013d000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b0000053c0020009c000000600000213d0000002401100370000000000101043b001100000001001d0000053c0010009c000000600000213d000000000020043f0000001101000039000000200010043f000000400100003914de14a50000040f0000001102000029000000000020043f000000200010043f000000400100003914de14a50000040f000000000101041a000000ff001001900000000001000039000000010100c039000000800010043f0000059b01000041000014df0001042e000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b001000000002001d0000002401100370000000000101043b001100000001001d0000053c0010009c000000600000213d000000000100041a0000053c021001970000000001000411000000000012004b000007b90000c13d000000110000006b000001660000613d0000001001000029000000000010043f0000000501000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000000000101041a000f00000001001d000000000001004b00000b600000c13d000005a801000041000000000010043f0000059701000041000014e0000104300000000001000416000000000001004b000000600000c13d0000000a01000039000007850000013d000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000002402100370000000000402043b0000000401100370000000000301043b000000000100041a0000053c021001970000000001000411000000000012004b000007b90000c13d0000000b01000039000000000101041a000000000001004b001100000003001d0000088a0000c13d000000000003004b000000000100001900000a610000613d001000000004001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000001102000029000000000021004b00000a5d0000a13d000005c701000041000000000010043f0000059701000041000014e000010430000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000002402100370000000000202043b001100000002001d0000053c0020009c000000600000213d0000000401100370000000000101043b000000000010043f0000000901000039000000200010043f000000400100003914de14a50000040f0000001102000029000000000020043f000000200010043f000000400100003914de14a50000040f0000000402100039000000000202041a0000000303100039000000000303041a0000000204100039000000000404041a0000000105100039000000000505041a000000000101041a000000800010043f000000a00050043f000000c00040043f000000e00030043f000001000020043f000005b401000041000014df0001042e000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b000005840020009c000000600000213d0000002304200039000000000034004b000000600000813d0000000404200039000000000441034f000000000504043b000005840050009c0000098c0000213d00000005045002100000003f064000390000058506600197000005860060009c0000098c0000213d0000008006600039001000000006001d000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000600000213d000000000005004b0000000003000019000004c90000613d0000008003000039000000000521034f000000000505043b0000053c0050009c000000600000213d000000200330003900000000005304350000002002200039000000000042004b000004b90000413d000000800100043d000005840010009c0000098c0000213d0000000002010019000000400100043d001000000001001d0000000003020019000200000003001d00000005013002100000003f0210003900000587032001970000001002300029000000000032004b00000000030000390000000103004039000005840020009c0000098c0000213d00000001003001900000098c0000c13d000000400020043f000000100200002900000002030000290000000005320436000000000003004b000600000005001d00000d4b0000c13d000000400100043d00000020020000390000000002210436000000100300002900000000030304330000000000320435000000400410003900000005023002100000000002420019000000000003004b00000d600000c13d0000000002120049000001d30000013d000000840030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000006402100370000000000502043b0000004402100370000000000302043b0000002402100370000000000402043b0000000401100370000000000201043b000000000100041a0000053c011001970000000006000411000000000061004b000009660000c13d0000000b07000039000000000107041a000000000001004b001100000002001d000e00000003001d001000000004001d0000089d0000c13d000000000005004b000009300000c13d14de10cc0000040f0000000801000039000000000101041a000000110010006c00000d5a0000a13d00000011010000290000000a011000c9000f00000001001d000005a50110009a000000000101041a0000053c0110019800000a040000c13d000005c401000041000000000010043f0000059701000041000014e0000104300000000001000416000000000001004b000000600000c13d14de10cc0000040f0000000001000019000014df0001042e000000e40030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b001100000002001d0000053c0020009c000000600000213d0000002402100370000000000202043b001000000002001d0000012002000039000000400020043f0000004402100370000000000202043b000000800020043f0000006402100370000000000202043b000000a00020043f0000008402100370000000000202043b000000c00020043f000000a402100370000000000202043b000000e00020043f000000c401100370000000000101043b000001000010043f0000059c0100004100000000001004430000000001000412000000040010044300000024000004430000000001000414000005390010009c0000053901008041000000c0011002100000059d011001c7000080050200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000053c011001970000000002000411000000000012004b000009920000c13d0000000801000039000000000101041a000000100010006b000009f90000813d000000a00100043d000000c00200043d000000000012001a00000f6f0000413d0000000001120019000000800200043d000000000012004b00000b8e0000c13d14de10cc0000040f0000001001000029000000000010043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b0000001102000029000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000301043b0000000801000039000000000101041a000000100010006c00000d5a0000a13d0000000801000039000000000010043f000000000103041a000000800200043d000000000012001a00000f6f0000413d000000000112001a00000010020000290000000a022000c90000058c0220009a000000000202041a000000000013041b00000000042100a9000005880000613d00000000051400d9000000000025004b00000f6f0000c13d0000058f0540012a0000000304300039000000000604041a000000000056001a00000f6f0000413d00000000055600190000000406300039001100000006001d000000000606041a000000000565004b00000f6f0000413d000000e00600043d000000000056001a00000f6f0000413d0000000005560019000000000054041b0000000104300039000000000504041a000000a00600043d000000000056001a00000f6f0000413d0000000005560019000000000054041b0000000203300039000000000403041a000000c00500043d000000000045001a00000f6f0000413d0000000004450019000000000043041b14de10be0000040f0000058f0110012a0000001102000029000000000012041b0000000001000019000014df0001042e0000000001000416000000000001004b000000600000c13d0000000101000039000006b30000013d0000000001000416000000000001004b000000600000c13d14de10a40000040f000000000001004b0000000001000039000000010100c039000000400200043d0000000000120435000005390020009c00000539020080410000004001200210000005a3011001c7000014df0001042e000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b0000000802000039000000000202041a000000000021004b000000600000813d14de10250000040f0000000802100039000000000202041a001100000002001d0000000702100039000000000202041a001000000002001d0000000602100039000000000202041a000f00000002001d0000000502100039000000000202041a000d00000002001d0000000402100039000000000202041a000c00000002001d0000000302100039000000000202041a000b00000002001d0000000202100039000000000202041a000a00000002001d0000000102100039000000000202041a000900000002001d000000000201041a000e00000002001d000000090110003914de10450000040f00000009020000290000053c02200197000000400400043d000900000004001d0000002003400039000000000023043500000040024000390000000a03000029000000000032043500000060024000390000000b03000029000000000032043500000080024000390000000c030000290000000000320435000000a0024000390000000d030000290000000000320435000000c0024000390000000f030000290000000000320435000000e002400039000000100300002900000000003204350000010002400039000000110300002900000000003204350000014002000039000001200340003900000000002304350000000e020000290000053c022001970000000000240435000001400240003914de10920000040f00000009020000290000000001210049000005390010009c0000053901008041000005390020009c000005390200804100000060011002100000004002200210000000000121019f000014df0001042e000000640030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b000e00000002001d0000002402100370000000000202043b000005840020009c000000600000213d0000002304200039000000000034004b000000600000813d0000000404200039000000000441034f000000000504043b000005840050009c0000098c0000213d00000005045002100000003f064000390000058506600197000005860060009c0000098c0000213d0000008006600039000000400060043f000000800050043f00000024022000390000000004240019000000000034004b000000600000213d000000000005004b000006400000613d0000008005000039000000000621034f000000000606043b0000053c0060009c000000600000213d000000200550003900000000006504350000002002200039000000000042004b000006370000413d0000004402100370000000000202043b000005840020009c000000600000213d0000002304200039000000000034004b0000000005000019000005b505008041000005b504400197000000000004004b0000000006000019000005b506004041000005b50040009c000000000605c019000000000006004b000000600000c13d0000000404200039000000000441034f000000000404043b000005840040009c0000098c0000213d00000005054002100000003f065000390000058506600197000000400700043d0000000006670019000d00000007001d000000000076004b00000000070000390000000107004039000005840060009c0000098c0000213d00000001007001900000098c0000c13d000000400060043f0000000d060000290000000006460436000c00000006001d00000024022000390000000005250019000000000035004b000000600000213d000000000004004b000006730000613d0000000c03000029000000000421034f000000000404043b00000000034304360000002002200039000000000052004b0000066d0000413d000000000100041a0000053c021001970000000001000411000000000012004b000007b90000c13d0000000d010000290000000002010433000000800100043d000000000021004b00000eda0000c13d0000000802000039000000000302041a0000000e0030006c00000d5a0000a13d000000000020043f0000000e020000290000000a022000c9000b00000002001d000005a50220009a000000000202041a0000053c00200198000005100000613d000000000001004b001000000000001d00000f210000c13d0000000b010000290000058b0110009a000000000201041a0000001003000029000000000032001a00000f6f0000413d0000000002320019000000000021041b0000000001000019000014df0001042e0000000001000416000000000001004b000000600000c13d000000000100041a000006b40000013d000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000002402100370000000000202043b0000000401100370000000000101043b001100000001001d0000000e01000039000000000101041a000000000001004b000007cf0000c13d000000000002004b000007e90000c13d000005c001000041000000000010043f0000059701000041000014e0000104300000000001000416000000000001004b000000600000c13d0000000301000039000000000101041a0000053c01100197000000800010043f0000059b01000041000014df0001042e0000000001000416000000000001004b000000600000c13d0000001301000039000007850000013d000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000601043b0000053c0060009c000000600000213d000000000100041a0000053c021001970000000001000411000000000012004b000007b90000c13d0000000201000039000000000201041a0000053d02200197000000000262019f000000000021041b0000000303000039000000000103041a00000000020004140000053c05100197000005390020009c0000053902008041000000c0012002100000053e011001c70000800d02000039000005a40400004114de14d40000040f0000000100200190000000600000613d0000000001000019000014df0001042e000000840030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000402100370000000000202043b001000000002001d0000002402100370000000000202043b001100000002001d0000053c0020009c000000600000213d0000004402100370000000000202043b000f00000002001d0000053c0020009c000000600000213d0000006401100370000000000101043b000e00000001001d0000000001000411000000000010043f0000001101000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b0000001102000029000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000000000101041a000000ff0010019000000b9f0000c13d000005c601000041000000000010043f0000059701000041000014e000010430000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d000000000200041a0000053c032001970000000002000411000000000023004b000007e40000c13d0000002402100370000000000202043b001100000002001d0000000401100370000000000101043b001000000001001d14de10cc0000040f0000001001000029000000000010043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f000000110000006b00000011030000290000058f03006041001100000003001d0000000100200190000000600000613d000000000101043b0000000101100039001000000001001d000000000101041a000000400200043d0000002003200039000000110400002900000000004304350000000000120435000005390020009c000005390200804100000040012002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f00000588011001c70000800d020000390000000103000039000005c10400004114de14d40000040f0000000100200190000000600000613d00000011010000290000001002000029000000000012041b0000000001000019000014df0001042e000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b000000000010043f0000001201000039000000200010043f000000400100003914de14a50000040f0000000102100039000000000202041a000000000101041a000000800010043f000000a00020043f000005b201000041000014df0001042e000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000002402100370000000000202043b0000053c0020009c000000600000213d0000000401100370000000000101043b14de13660000040f000005b80000013d000000440030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000101043b0000053c0010009c000000600000213d000000800000043f0000059b01000041000014df0001042e0000000001000416000000000001004b000000600000c13d0000000601000039000000000101041a000000800010043f0000059b01000041000014df0001042e000000240030008c000000600000413d0000000002000416000000000002004b000000600000c13d0000000401100370000000000301043b000000000100041a0000053c021001970000000001000411000000000012004b000007b90000c13d0000000b01000039000000000101041a000000000001004b000008b10000c13d0000058f0130009a000005910010009c00000f070000213d001100000003001d14de10cc0000040f0000000701000039000000000101041a000000400200043d0000002003200039000000110400002900000000004304350000000000120435000005390020009c000005390200804100000040012002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f00000588011001c70000800d020000390000000103000039000005920400004114de14d40000040f0000000100200190000000600000613d00000011010000290000000702000039000000000012041b0000000001000019000014df0001042e0000059002000041000000000020043f000000040010043f0000054201000041000014e0000104300000001102000029000000a00020043f0000014000000443000001600010044300000020010000390000018000100443000001a0002004430000010000100443000000020100003900000120001004430000054001000041000014df0001042e0000059001000041000000000010043f000000040050043f0000054201000041000014e000010430000f00000001001d001000000002001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000f0010006c0000001002000029000006a90000a13d000005bd01000041000000000010043f0000059701000041000014e0000104300000059001000041000000000010043f000000040020043f0000054201000041000014e000010430001000000002001d14de10cc0000040f0000000801000039000000000101041a000000110010006c00000d5a0000a13d0000001101000029000000000010043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b00000000020004110000053c02200197000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b0000000204100039000000000c04041a0000001005000029000005cf0050009c000000000800001900000000030c001900000c0f0000613d0000000000c5004b00000000080000390000000108002039000000000305001900000c0f0000a13d000005be01000041000000000010043f0000000400c0043f0000054201000041000014e000010430000005390010009c0000053901008041000000c00110021000000595011001c714de14d90000040f00000060031002700000053903300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000080057001bf000008300000613d0000008008000039000000000901034f000000009a09043c0000000008a80436000000000058004b0000082c0000c13d000000000006004b0000083d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000009960000613d0000001f01400039000000600110018f00000080011001bf000000400010043f000000200030008c000000600000413d000000800100043d0000053c0010009c000000600000213d0000000002000411000000000012004b00000a000000c13d00000598010000410000000000100443000000110100002900000004001004430000000001000414000005390010009c0000053901008041000000c00110021000000599011001c7000080020200003914de14d90000040f000000010020019000000f200000613d000000000101043b000000000001004b000000600000613d000000400200043d0000059a01000041001000000002001d000000000012043500000000010004140000001102000029000000040020008c000008750000613d0000001002000029000005390020009c00000539020080410000004002200210000005390010009c0000053901008041000000c001100210000000000121019f00000597011001c7000000110200002914de14d40000040f0000006003100270000105390030019d0003000000010355000000010020019000000ec90000613d0000001001000029000000000200001914de10330000040f0000000001000019000014df0001042e000e00000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000e0010006c000003bd0000a13d000008c20000013d000f00000001001d001000000004001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000f0010006c000000110300002900000010040000290000045a0000a13d000008c20000013d000d00000001001d000f00000005001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000d0010006c0000000f0500002900000000060004110000000b07000039000005020000a13d000008c20000013d001000000001001d001100000003001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b000000100010006c0000001103000029000007990000a13d000005ca01000041000000000010043f0000059701000041000014e00001043014de10cc0000040f0000000801000039000000000101041a000000100010006c00000d5a0000a13d0000001001000029000000000010043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b00000000020004110000053c02200197000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d0000000f020000290000058c0220009a000000000502041a000000000301043b000000000403041a00000000014500a9000000000004004b0000001108000029000008f20000613d00000000064100d9000000000056004b00000f6f0000c13d0000058f0110012a0000000305300039000000000605041a000000000016001a00000f6f0000413d00000000061600190000000401300039000000000701041a000000000676004b00000f6f0000413d000000000065041b0000000205300039000000000605041a000000000086001a00000f6f0000413d0000000006860019000000000065041b0000000f05000029000005ad0550009a000000000605041a000000000086001a00000f6f0000413d0000000006860019000000000065041b000000000084001a00000f6f0000413d0000000004840019000000000043041b0000000f030000290000058a0330009a000000000503041a000000000085001a00000f6f0000413d0000000005850019000000000053041b000000000302041a00000000024300a9000000000004004b0000091c0000613d00000000044200d9000000000034004b00000f6f0000c13d0000058f0220012a000000000021041b000000400100043d00000000028104360000000000020435000005390010009c000005390100804100000040011002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f00000588011001c70000800d020000390000000303000039000005cb0400004100000000050004110000001006000029000006da0000013d000000000100041a0000053c01100197000000000061004b000009660000c13d000000000107041a000d00000001001d000000000001004b000f00000005001d000009480000613d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000d0010006c0000000f05000029000008c20000213d0000058f0150009a000005b70010009c00000f070000813d14de10cc0000040f0000000701000039000000000101041a000000400200043d00000020032000390000000f0400002900000000004304350000000000120435000005390020009c000005390200804100000040012002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f00000588011001c70000800d020000390000000103000039000005920400004114de14d40000040f0000000100200190000000600000613d0000000f010000290000000702000039000000000012041b000005050000013d0000059001000041000000000010043f000000040060043f0000054201000041000014e000010430000005bb0030009c0000098c0000213d000000600300003900000000040000190000014005100039000000400050043f0000012005100039000000000035043500000100051000390000000000050435000000e0051000390000000000050435000000c0051000390000000000050435000000a0051000390000000000050435000000800510003900000000000504350000006005100039000000000005043500000040051000390000000000050435000000200510003900000000000504350000000000010435000000a00540003900000000001504350000002004400039000000000024004b00000a6b0000813d000000400100043d000005aa0010009c0000096f0000a13d000005bc01000041000000000010043f0000004101000039000000040010043f0000054201000041000014e0000104300000059e01000041000000000010043f0000059701000041000014e0000104300000001f0530018f0000053b06300198000000400200043d0000000004620019000009a10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000099d0000c13d000000000005004b000009ae0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000005390020009c00000539020080410000004002200210000000000112019f000014e000010430000000a00400003900000140050000390000000007000019000009c00000013d0000001f0a900039000005ce0aa00197000000000998001900000000000904350000000008a800190000000107700039000000000027004b000001d20000813d0000000009180049000000400990008a0000000003930436000000004904043400000000ba0904340000053c0aa00197000000000aa80436000000000b0b04330000053c0bb001970000000000ba0435000000400a900039000000000a0a0433000000400b8000390000000000ab0435000000600a900039000000000a0a0433000000600b8000390000000000ab0435000000800a900039000000000a0a0433000000800b8000390000000000ab0435000000a00a900039000000000a0a0433000000a00b8000390000000000ab0435000000c00a900039000000000a0a0433000000c00b8000390000000000ab0435000000e00a900039000000000a0a0433000000e00b8000390000000000ab0435000001000a900039000000000a0a0433000001000b8000390000000000ab043500000120099000390000000009090433000001200a80003900000000005a0435000001400b80003900000000a909043400000000009b04350000016008800039000000000009004b000009b80000613d000000000b000019000000000c8b0019000000000dba0019000000000d0d04330000000000dc0435000000200bb0003900000000009b004b000009f10000413d000009b80000013d000000400100043d00000044021000390000059f03000041000000000032043500000024021000390000000f0300003900000b940000013d0000059601000041000000000010043f0000059701000041000014e000010430000d00000001001d000000000010043f0000000d01000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000000000101041a000000ff00100190000005100000613d000000100000006b00000a280000613d0000001101000029000000000010043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b00000001011000390000001002000029000000000021041b0000000e0000006b00000a4d0000613d0000000f01000029000005890110009a000f00000001001d000000000101041a001000000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b000000100010006c00000a4d0000813d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000e0010006c0000000e0100a0290000000f02000029000000000012041b000000400100043d0000000000010435000005390010009c000005390100804100000040011002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f000005a6011001c70000800d020000390000000303000039000005b9040000410000000d0500002900000b8c0000013d0000001001000029000000000021001a00000f6f0000413d0000000001210019001000000001001d14de10cc0000040f0000000b010000390000001102000029000000000021041b0000000e010000390000001002000029000000000021041b0000000001000019000014df0001042e00000000050000190000000801000039000000000101041a000000000051004b00000d5a0000a13d000000400600043d000005aa0060009c0000098c0000213d0000014001600039000000400010043f0000000a015000c9000005a50210009a000000000202041a0000053c022001970000000002260436000005ab0310009a000000000303041a0000053c03300197000000000032043500000040026000390000058a0710009a000000000307041a0000000000320435000005ac0210009a000000000202041a00000060036000390000000000230435000005ad0210009a000000000202041a00000080036000390000000000230435000005ae0210009a000000000202041a000000a0036000390000000000230435000000c002600039000005890810009a000000000308041a0000000000320435000000e0026000390000058c0910009a000000000309041a000000000032043500000100026000390000058b0a10009a00000000030a041a0000000000320435000005af0110009a000000000201041a0000000103200190000000010c2002700000007f0cc0618f0000001f00c0008c00000000040000390000000104002039000000000043004b000002f20000c13d000000400b00043d0000000004cb0436000000000003004b001100000005001d00000ad00000613d000800000004001d00090000000c001d000b0000000b001d000c0000000a001d000d00000009001d000e00000008001d000f00000007001d001000000006001d000000000010043f0000000001000414000005390010009c0000053901008041000000c001100210000005a6011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000090c00002900000000000c004b00000ad60000613d000000000201043b0000000001000019000000110500002900000010060000290000000f070000290000000e080000290000000d090000290000000c0a0000290000000b0b000029000000080d00002900000000031d0019000000000402041a0000000000430435000000010220003900000020011000390000000000c1004b00000ac80000413d00000ade0000013d000005cd01200197000000000014043500000000000c004b0000002001000039000000000100603900000ade0000013d0000000001000019000000110500002900000010060000290000000f070000290000000e080000290000000d090000290000000c0a0000290000000b0b0000290000003f01100039000005ce021001970000000001b20019000000000021004b00000000020000390000000102004039000005840010009c0000098c0000213d00000001002001900000098c0000c13d000000400010043f00000120016000390000000000b10435000000800100043d000000000051004b00000d5a0000a13d0000000501500210000000a001100039000c00000001001d0000000000610435000000800100043d000000000051004b00000d5a0000a13d0000000801000039000000000101041a000000000051004b00000d5a0000a13d0000000801000039000000000010043f000000000108041a000d00000001001d0000001301000039000000000101041a000e00000001001d000000000107041a000f00000001001d00000000010a041a001000000001001d000000000109041a000b00000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000d06000029000000000061004b0000001105000029000000100400002900000b540000a13d0000000f0000006b00000b540000613d0000000e0000006b00000b540000613d0000000b02000039000000000202041a000000000012004b00000000030100190000000003024019000000000002004b000000000103c019000000000261004b000000000300001900000b330000a13d0000058f012000d100000000022100d90000058f0020009c00000f6f0000c13d000000000001004b00000b320000613d0000000702000039000000000202041a00000000031200a900000000011300d9000000000021004b00000b330000613d00000f6f0000013d0000000003000019000d00000003001d000000000050043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000000000201041a0000000d0300002900000000013200a9000000000003004b0000001105000029000000100400002900000b4b0000613d00000000033100d9000000000023004b00000f6f0000c13d0000000e021000fa0000058f0120012a000000000041001a00000f6f0000413d0000000f022000fa000005cf022001670000000b0020006b00000f6f0000213d0000000004410019000000800100043d000000000051004b00000d5a0000a13d0000000c0100002900000000010104330000010001100039000000000041043500000001055000390000000a0050006c00000a6c0000413d000000400100043d000001c90000013d0000000801000039000000000201041a000000100020006c00000d5a0000a13d000000000010043f00000010010000290000000a011000c9000005a50110009a000000000101041a0000053c0110019700000011020000290000000f0300002914de12bf0000040f0000001001000029000000000010043f0000000501000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000000000001041b000000400100043d0000000f020000290000000000210435000005390010009c000005390100804100000040011002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f000005a6011001c70000800d020000390000000303000039000005a70400004100000010050000290000001106000029000006da0000013d000000400100043d0000004402100039000005a2030000410000000000320435000000240210003900000014030000390000000000320435000005a0020000410000000000210435000000040210003900000020030000390000000000320435000005390010009c00000539010080410000004001100210000005a1011001c7000014e0000104300000000f010000290000053c02100197000000110020006b00000c560000613d0000000001000410000000000012004b00000c560000613d0000000e0000006b00000c560000613d000f00000002001d14de10cc0000040f0000000801000039000000000101041a000000100010006c00000d5a0000a13d00000010010000290000000a011000c9000005a50210009a000000000202041a0000053c00200198000005100000613d0000058c0110009a000000000101041a000d00000001001d0000001001000029000000000010043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b0000001102000029000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000c00000001001d0000001001000029000000000010043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b0000000f02000029000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d0000000c02000029000000000202041a0000000d032000b9000000000701043b000000000107041a000000000002004b00000bf70000613d00000000042300d90000000d0040006c00000f6f0000c13d0000058f0430012a0000000c050000290000000308500039000000000508041a000000000045001a00000f6f0000413d00000000054500190000000c060000290000000406600039000000000906041a000000000995004b00000f6f0000413d000000010500008a0000000e0050006b000000000509001900000f5d0000613d0000000e05000029000000000095004b00000f5d0000a13d000005c201000041000000000010043f000000040090043f0000054201000041000014e00001043000000011020000290000000a022000c90000058c0620009a000000000906041a000000000501041a00000000075900a9000000000005004b00000c1a0000613d000000000a5700d900000000009a004b00000f6f0000c13d0000058f0770012a0000000309100039000000000a09041a00000000007a001a00000f6f0000413d000000000a7a00190000000407100039000000000b07041a000000000aba004b00000f6f0000413d0000000000a9041b000000010080019000000f6f0000c13d00000000083c0049000000000084041b000005ad0820009a000000000408041a000000000434004b00000f6f0000413d000000000048041b000000000835004b00000f6f0000413d000000000081041b0000058a0120009a000000000401041a000000000434004b00000f6f0000413d000000000041041b000000000406041a00000000018400a9000000000035004b00000c3d0000613d00000000058100d9000000000045004b00000f6f0000c13d000005a50220009a0000058f0110012a000000000017041b000000000102041a0000053c011001970000000002000411001000000003001d14de12bf0000040f000000400100043d00000010020000290000000000210435000005390010009c000005390100804100000040011002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f000005a6011001c70000800d020000390000000303000039000005bf04000041000000000500041100000b8c0000013d000005c501000041000000000010043f0000059701000041000014e00001043000000060020000390000000003000019000000000453001900000000002404350000002003300039000000000013004b00000c5c0000413d0000000801000039000000000101041a000700000001001d000005840010009c00000d570000213d000000070100002900000005021002100000003f01200039000205850010019b000400000002001d0001001f00200193000080100900003900000000020000190000000b0800002900000c740000013d00000009020000290000000102200039000000030020006c0000035e0000813d000000800100043d000900000002001d000000000021004b00000d5a0000a13d000000400100043d0000000204100029000000000014004b00000000020000390000000102004039000005840040009c0000098c0000213d00000001002001900000098c0000c13d00000009020000290000000503200210000000a0023000390000000002020433000000400040043f00000007040000290000000004410436000000040000006b00000c910000613d000000040540002900000000060000310000000206600367000000006706043c0000000004740436000000000054004b00000c8d0000c13d000000010000006b00000008040000290000000004040433000000090040006c00000d5a0000a13d0000000003830019000600000003001d000000000013043500000008010000290000000001010433000000090010006c00000d5a0000a13d000000070000006b00000c700000613d0005053c0020019b0000000004000019001100000004001d000000000040043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000000000209001914de14d90000040f0000000100200190000000600000613d000000000101043b0000000502000029000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b001000000001001d0000000801000039000000000101041a0000001102000029000000000021004b00000d5a0000a13d0000000801000039000000000010043f0000000a012000c90000001302000039000000000202041a000d00000002001d000005890210009a000000000202041a000c00000002001d0000058a0210009a000000000202041a000e00000002001d0000058b0210009a000000000202041a000a00000002001d0000058c0110009a000000000101041a000f00000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000c07000029000000000071004b0000000b080000290000801009000039000000110400002900000010050000290000000f0600002900000d290000a13d0000000e0000006b00000d290000613d0000000d0000006b00000d290000613d0000000b02000039000000000202041a000000000012004b00000000030100190000000003024019000000000002004b000000000103c019000000000271004b000000000300001900000d040000a13d0000058f012000d100000000022100d90000058f0020009c00000f6f0000c13d000000000001004b00000d030000613d0000000702000039000000000202041a00000000031200a900000000011300d9000000000021004b00000d040000613d00000f6f0000013d0000000003000019000c00000003001d000000000040043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000000000209001914de14d90000040f0000000100200190000000600000613d000000000101043b000000000201041a0000000c0300002900000000013200a9000000000003004b0000000b080000290000801009000039000000110400002900000010050000290000000f0600002900000d1f0000613d00000000033100d9000000000023004b00000f6f0000c13d000000010200008a0000000a0220014f0000000d011000fa0000058f0310012a000000000023004b00000f6f0000213d0000000e011000fa000000000061001a00000f6f0000413d0000000006610019000000000205041a00000000016200a9000000000002004b00000d300000613d00000000022100d9000000000062004b00000f6f0000c13d0000058f0110012a0000000302500039000000000202041a000000000012001a00000f6f0000413d00000000011200190000000402500039000000000202041a000000000121004b00000f6f0000413d00000008020000290000000002020433000000090020006c00000d5a0000a13d000000060200002900000000020204330000000003020433000000000043004b00000d5a0000a13d00000005034002100000000002230019000000200220003900000000001204350000000104400039000000070040006c00000ca10000413d00000c700000013d00000060020000390000000003000019000000000453001900000000002404350000002003300039000000000013004b00000d4d0000413d0000000801000039000000000101041a000400000001001d000005840010009c00000d7d0000a13d000000800100043d000000000001004b0000098c0000c13d000005bc01000041000000000010043f0000003201000039000000040010043f0000054201000041000014e0000104300000000005000019000000060d00002900000d660000013d0000000105500039000000000035004b000004e70000813d0000000006120049000000400660008a000000000464043600000000d60d043400000000070604330000000002720436000000000007004b00000d630000613d000000000800001900000020066000390000000009060433000000000a000019000000000b020019000000009c090434000000000bcb04360000000300a0008c000000010aa0003900000d730000413d00000080022000390000000108800039000000000078004b00000d6f0000413d00000d630000013d00000004010000290000000501100210000300000001001d0000003f01100039000105850010019b000080100d000039000000000e000019000000060c00002900000d890000013d000000010ee000390000000200e0006c000004dc0000813d000000800100043d0000000000e1004b00000d5a0000a13d000000400100043d0000000104100029000000000014004b00000000020000390000000102004039000005840040009c0000098c0000213d00000001002001900000098c0000c13d0000000503e00210000000a0023000390000000002020433000000400040043f00000004050000290000000004510436000000000005004b00000db00000613d000000000500003100000002055003670000000006000019000000400700043d000005860070009c0000098c0000213d0000008008700039000000400080043f000000000905034f000000000a070019000000009b09043c000000000aba043600000000008a004b00000da70000c13d000000000864001900000000007804350000002006600039000000030060006c00000da00000413d000000100400002900000000040404330000000000e4004b00000d5a0000a13d0000000003c30019000f00000003001d0000000000130435000000100100002900000000010104330000000000e1004b00000d5a0000a13d000000040000006b00000d860000613d0008053c0020019b0000000004000019000d0000000e001d001100000004001d000000000040043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c700000000020d001914de14d90000040f0000000100200190000000600000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000400400043d000005b30040009c00008010080000390000000d09000029000000110a0000290000098c0000213d000000000501043b000000a001400039000000400010043f000000000305041a00000000023404360000000101500039000000000101041a00000000001204350000000201500039000000000601041a000000400140003900000000006104350000000306500039000000000606041a0000006007400039000000000067043500000080044000390000000405500039000000000505041a000000000054043500000010040000290000000004040433000000000094004b00000d5a0000a13d0000000f04000029000000000404043300000000050404330000000000a5004b00000d5a0000a13d0000000505a00210000e00200050003d0000000e044000290000000004040433000000000034043500000010030000290000000003030433000000000093004b00000d5a0000a13d0000000f03000029000000000303043300000000040304330000000000a4004b00000d5a0000a13d00000000020204330000000e0330002900000000030304330000002003300039000000000023043500000010020000290000000002020433000000000092004b00000d5a0000a13d0000000f02000029000000000202043300000000030204330000000000a3004b00000d5a0000a13d00000000010104330000000e022000290000000002020433000000400220003900000000001204350000000000a0043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000000000208001914de14d90000040f0000000100200190000000600000613d000000000101043b0000000802000029000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b000c00000001001d0000000801000039000000000101041a0000001102000029000000000021004b00000d5a0000a13d0000000801000039000000000010043f0000000a012000c90000001302000039000000000202041a000900000002001d000005890210009a000000000202041a000700000002001d0000058a0210009a000000000202041a000a00000002001d0000058b0210009a000000000202041a000500000002001d0000058c0110009a000000000101041a000b00000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000707000029000000000071004b000000060c000029000080100d0000390000000d0e00002900000011040000290000000c050000290000000b0600002900000ea70000a13d0000000a0000006b00000ea70000613d000000090000006b00000ea70000613d0000000b02000039000000000202041a000000000012004b00000000030100190000000003024019000000000002004b000000000103c019000000000271004b000000000300001900000e810000a13d0000058f012000d100000000022100d90000058f0020009c00000f6f0000c13d000000000001004b00000e800000613d0000000702000039000000000202041a00000000031200a900000000011300d9000000000021004b00000e810000613d00000f6f0000013d0000000003000019000700000003001d000000000040043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c700000000020d001914de14d90000040f0000000100200190000000600000613d000000000101043b000000000201041a000000070300002900000000013200a9000000000003004b000000060c000029000080100d0000390000000d0e00002900000011040000290000000c050000290000000b0600002900000e9d0000613d00000000033100d9000000000023004b00000f6f0000c13d000000010200008a000000050220014f00000009011000fa0000058f0310012a000000000023004b00000f6f0000213d0000000a011000fa000000000061001a00000f6f0000413d0000000006610019000000000205041a00000000016200a9000000000002004b00000eae0000613d00000000022100d9000000000062004b00000f6f0000c13d0000058f0110012a0000000302500039000000000202041a000000000012001a00000f6f0000413d00000000011200190000000402500039000000000202041a000000000121004b00000f6f0000413d000000100200002900000000020204330000000000e2004b00000d5a0000a13d0000000f0200002900000000020204330000000003020433000000000043004b00000d5a0000a13d0000000e022000290000000002020433000000600220003900000000001204350000000104400039000000040040006c00000dc00000413d00000d860000013d00000539033001970000001f0530018f0000053b06300198000000400200043d0000000004620019000009a10000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000ed10000c13d000009a10000013d000005a901000041000000000010043f0000059701000041000014e000010430000005b601000041000000000010043f0000059701000041000014e000010430000000000100041a0000053c011001970000000002000411000000000021004b00000f0b0000c13d0000000b01000039000000000101041a000d00000001001d000000000001004b00000f110000c13d0000000f010000290000058f0110009a000005910010009c00000f070000213d14de10cc0000040f0000000701000039000000000101041a000000400200043d00000020032000390000000f0400002900000000004304350000000000120435000005390020009c000005390200804100000040012002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f00000588011001c70000800d020000390000000103000039000005920400004114de14d40000040f0000000100200190000000600000613d0000000f010000290000000702000039000000000012041b000002760000013d000005b801000041000000000010043f0000059701000041000014e0000104300000059001000041000000000010043f0000000001000411000000040010043f0000054201000041000014e0000104300000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f000000010020019000000f200000613d000000000101043b0000000d0010006c000008c20000213d00000ee80000013d000000000001042f001100000000001d001000000000001d0000000e01000029000000000010043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000800200043d0000001103000029000000000032004b00000d5a0000a13d000000000101043b0000000502300210000f00000002001d000000a00220003900000000020204330000053c02200197000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000000101043b0000000d0200002900000000020204330000001105000029000000000052004b00000d5a0000a13d00000003021000390000000f030000290000000c013000290000000001010433000000000302041a000000000031001a000000100400002900000f6f0000413d0000000003310019000000000032041b000000000041001a00000f6f0000413d001000000041001d001100010050003d000000800100043d000000110010006b00000f230000413d0000068c0000013d0000000009590049000000000098041b0000000d081000b9000000000001004b00000f650000613d00000000091800d90000000d0090006c00000f6f0000c13d0000058f0980012a000000030a700039000000000b0a041a00000000009b001a00000f6f0000413d000000000b9b00190000000407700039000000000c07041a000000000bcb004b00000f750000813d000005bc01000041000000000010043f0000001101000039000000040010043f0000054201000041000014e00001043000000000005b001a00000f6f0000413d000000000b5b00190000000000ba041b000000000002004b00000f7e0000613d00000000022300d90000000d0020006c00000f6f0000c13d000000000046041b000000000001004b00000f840000613d00000000011800d90000000d0010006c00000f6f0000c13d000000000097041b000000400100043d0000000000510435000005390010009c000005390100804100000040011002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f000005a6011001c70000800d020000390000000403000039000005c30400004100000011050000290000000f06000029000000100700002914de14d40000040f0000000100200190000000600000613d000006dd0000013d0000000a01000029000000200010008c00000fb90000413d0000000b01000029000000000010043f0000000001000414000005390010009c0000053901008041000000c001100210000005a6011001c7000080100200003914de14d90000040f0000000100200190000000600000613d0000000e030000290000001f023000390000000502200270000000200030008c0000000002004019000000000301043b0000000a010000290000001f01100039000000050110027000000000011300190000000002230019000000000012004b00000fb90000813d000000000002041b0000000102200039000000000012004b00000fb50000413d0000000e010000290000001f0010008c00000fcd0000a13d0000000b01000029000000000010043f0000000001000414000005390010009c0000053901008041000000c001100210000005a6011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000200200008a0000000e02200180000000000101043b00000fda0000c13d000000200300003900000fe70000013d0000000e0000006b000000000100001900000fd20000613d0000000c0100002900000000010104330000000e040000290000000302400210000005cf0220027f000005cf02200167000000000121016f0000000102400210000000000121019f00000ff50000013d000000010320008a00000005033002700000000004310019000000200300003900000001044000390000000d0600002900000000056300190000000005050433000000000051041b00000020033000390000000101100039000000000041004b00000fe00000c13d0000000e0020006c00000ff20000813d0000000e020000290000000302200210000000f80220018f000005cf0220027f000005cf022001670000000d033000290000000003030433000000000223016f000000000021041b0000000e01000029000000010110021000000001011001bf0000000b02000029000000000012041b0000000f01000029000000000010043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000000600000613d000000100000006b00000010020000290000058f02006041000000000101043b0000000101100039000000000021041b000000400100043d0000000000010435000005390010009c000005390100804100000040011002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f000005a6011001c70000800d020000390000000303000039000005b00400004100000011050000290000000f0600002914de14d40000040f0000000100200190000000600000613d000000400100043d0000000f020000290000000000210435000005390010009c00000539010080410000004001100210000005a3011001c7000014df0001042e0000000802000039000000000302041a000000000013004b0000102d0000a13d000000000020043f0000000a011000c9000005a50110009a000000000001042d000005bc01000041000000000010043f0000003201000039000000040010043f0000054201000041000014e0000104300000001f02200039000005ce022001970000000001120019000000000021004b00000000020000390000000102004039000005840010009c0000103f0000213d00000001002001900000103f0000c13d000000400010043f000000000001042d000005bc01000041000000000010043f0000004101000039000000040010043f0000054201000041000014e0000104300003000000000002000000000201041a000000010320019000000001062002700000007f0660618f0000001f0060008c00000000040000390000000104002039000000000043004b000010840000c13d000000400500043d0000000004650436000000000003004b0000106f0000613d000100000004001d000300000006001d000200000005001d000000000010043f0000000001000414000005390010009c0000053901008041000000c001100210000005a6011001c7000080100200003914de14d90000040f0000000100200190000010900000613d0000000306000029000000000006004b000010750000613d000000000201043b0000000001000019000000020500002900000001070000290000000003170019000000000402041a000000000043043500000001022000390000002001100039000000000061004b000010670000413d000010770000013d000005cd012001970000000000140435000000000006004b00000020010000390000000001006039000010770000013d000000000100001900000002050000290000003f01100039000005ce021001970000000001520019000000000021004b00000000020000390000000102004039000005840010009c0000108a0000213d00000001002001900000108a0000c13d000000400010043f0000000001050019000000000001042d000005bc01000041000000000010043f0000002201000039000000040010043f0000054201000041000014e000010430000005bc01000041000000000010043f0000004101000039000000040010043f0000054201000041000014e0000104300000000001000019000014e00001043000000000430104340000000001320436000000000003004b0000109e0000613d000000000200001900000000052100190000000006240019000000000606043300000000006504350000002002200039000000000032004b000010970000413d000000000231001900000000000204350000001f02300039000005ce022001970000000001210019000000000001042d00010000000000020000000e01000039000000000101041a000000000001004b000010bb0000613d000100000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f0000000100200190000010bd0000613d000000000101043b000000010010006c00000000010000390000000101002039000000010110018f000000000001042d000000010100018f000000000001042d000000000001042f000000000301001900000000011200a9000000000003004b000010c50000613d00000000033100d9000000000023004b000010c60000c13d000000000001042d000005bc01000041000000000010043f0000001101000039000000040010043f0000054201000041000014e000010430000d0000000000020000000801000039000000000101041a000500000001001d000005ba0010009c000012780000813d000000050100002900000005011002100000003f021000390000058502200197000000400300043d0000000002230019000a00000003001d000000000032004b00000000030000390000000103004039000005840020009c000012780000213d0000000100300190000012780000c13d000000400020043f00000005020000290000000a030000290000000003230436000900000003001d000000000002004b0000126f0000613d000000000200003100000002022003670000000003000019000000400400043d000005860040009c000012780000213d0000008005400039000000400050043f000000000602034f0000000007040019000000006806043c0000000007870436000000000057004b000010f10000c13d000000090530002900000000004504350000002003300039000000000013004b000010ea0000413d00000000020000190000000005000019000b00000002001d000000400600043d000005860060009c000012780000213d0000008001600039000000400010043f000000000200003100000002022003670000000003060019000000002402043c0000000003430436000000000013004b000011050000c13d0000000801000039000000000101041a000000000051004b000012720000a13d0000000801000039000000000010043f000800000005001d0000000a015000c9000300000001001d000005890110009a000000000101041a000700000006001d000400000001001d0000000001160436000600000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f00000001002001900000127e0000613d000000000101043b000000040010006c00000008050000290000000706000029000011c30000413d000400000001001d000000000050043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000706000029000000080500002900000001002001900000127f0000613d000000000301043b000000000103041a000000060200002900000000001204350000000001060433000000040010006b000011c30000613d000000400260003900000003010000290000058a0110009a000000000101041a0000000000120435000000000001004b000011c30000613d000100000002001d000200000003001d0000000301000029000005a50110009a000000000101041a000000400300043d000005d00200004100000000002304350000053c01100197000400000003001d000000040230003900000000001204350000059c01000041000000000010044300000000010004120000000400100443000000200100003900000024001004430000000001000414000005390010009c0000053901008041000000c0011002100000059d011001c7000080050200003914de14d90000040f00000001002001900000127e0000613d000000000201043b00000000010004140000053c02200197000000040020008c0000116d0000c13d0000000103000031000000200030008c0000002004000039000000000403401900000008050000290000000706000029000000040a000029000011990000013d0000000403000029000005390030009c00000539030080410000004003300210000005390010009c0000053901008041000000c001100210000000000131019f00000542011001c714de14d90000040f000000040a00002900000060031002700000053903300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000011860000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000011820000c13d0000001f07400190000011930000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000012870000613d000000080500002900000007060000290000001f01400039000000600210018f0000000001a20019000000000021004b00000000020000390000000102004039000005840010009c000012780000213d0000000100200190000012780000c13d000000400010043f000000200030008c00000002040000290000127f0000413d00000000010a043300000060026000390000000000120435000000000001004b0000000102000029000011c30000613d0000000003020433000000000003004b000011c30000613d00000000021300a900000000033200d9000000000013004b000012810000c13d0000058f0020009c000011c30000413d0000000101400039000000000301041a0000058f0220012a00000000012300a900000000022100d9000000000032004b000012810000c13d0000058f0010009c000011c30000413d0000058f0110012a000000000014041b000000060200002900000000001204350000000a010000290000000001010433000000000051004b000012720000a13d0000000501500210000000090110002900000000006104350000000a010000290000000001010433000000000051004b000012720000a13d000000060100002900000000010104330000000b0010002a000012810000413d0000000b021000290000000105500039000000050050006c000010fc0000413d0000001301000039000b00000002001d000000000021041b0000000701000039000000000101041a000300000001001d0000000002000019000011fb0000013d000005890220009a000000000012041b00000000010b04330000006002a000390000000002020433000000400300043d000000200430003900000000002404350000000000130435000005390030009c000005390300804100000040013002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f00000588011001c70000800d020000390000000203000039000005d104000041000000000509001914de14d40000040f00000001002001900000127f0000613d00000008020000290000000102200039000000050020006c0000126e0000813d0000000a010000290000000001010433000000000021004b000012720000a13d0000000801000039000000000101041a000000000021004b000012720000a13d000800000002001d0000000501200210000000090110002900000000020104330000000801000039000000000010043f000600000002001d0000000012020434000700000002001d000400000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f00000001002001900000127e0000613d000000000101043b000000070010006c000011f70000a13d00000008090000290000000a029000c9000000060a0000290000004003a000390000000003030433000000000003004b000000040b000029000011de0000613d00000000040b0433000000000004004b000011de0000613d0000000b05000039000000000505041a000000000015004b00000000060100190000000006054019000000000005004b000000000601601900000000050004150000000d0550008a000000050550021000000000070a0433000000000776004b00000000060000190000124f0000a13d0000058f067000d100000000057600d90000058f0050009c000012810000c13d00000000050004150000000d0550008a0000000505500210000000000006004b0000124e0000613d00000003076000b900000000056700d9000000030050006c000012810000c13d00000000050004150000000c0550008a0000000505500210000000000007004b000012640000613d00000000050004150000000c0550008a000000050550021000000000067400a900000000077600d9000000000047004b0000124f0000613d000012810000013d00000000060000190000000b04000029000000000004004b000012680000613d00000000044600d90000000505500270000000000504001f0000058f0640012a0000058b0520009a000000000705041a000000000067001a000012810000413d0000000006670019000000000065041b00000000043400d90000058c0320009a000000000503041a000000000045001a000012810000413d0000000004450019000000000043041b000011de0000013d00000000060000190000000b04000029000000000004004b000012520000c13d000005bc01000041000000000010043f0000001201000039000000040010043f0000054201000041000014e000010430000000000001042d0000001301000039000000000001041b000000000001042d000005bc01000041000000000010043f0000003201000039000000040010043f0000054201000041000014e000010430000005bc01000041000000000010043f0000004101000039000000040010043f0000054201000041000014e000010430000000000001042f0000000001000019000014e000010430000005bc01000041000000000010043f0000001101000039000000040010043f0000054201000041000014e0000104300000001f0530018f0000053b06300198000000400200043d0000000004620019000012920000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000128e0000c13d000000000005004b0000129f0000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000005390020009c00000539020080410000004002200210000000000112019f000014e00001043000010000000000020000000b01000039000000000101041a000000000001004b000012bc0000613d000100000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f0000000100200190000012be0000613d000000000101043b000000010010006c00000000010000390000000101002039000000010110018f000000000001042d000000010100018f000000000001042d000000000001042f0003000000000002000000400400043d000000440540003900000000003504350000002003400039000005d20500004100000000005304350000053c022001970000002405400039000000000025043500000044020000390000000000240435000005d30040009c000013440000813d0000008002400039000000400020043f000000000404043300000000020004140000053c09100197000000040090008c000013020000c13d00000001020000390000000101000031000000000001004b000013180000613d000005840010009c000013440000213d0000001f04100039000005ce044001970000003f04400039000005ce04400197000000400b00043d00000000044b00190000000000b4004b00000000050000390000000105004039000005840040009c000013440000213d0000000100500190000013440000c13d000000400040043f000000000a1b0436000005ce031001980000001f0410018f00000000013a00190000000305000367000012f40000613d000000000605034f00000000070a0019000000006806043c0000000007870436000000000017004b000012f00000c13d000000000004004b0000131a0000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f00000000003104350000131a0000013d000005390030009c00000539030080410000004001300210000005390040009c00000539040080410000006003400210000000000113019f000005390020009c0000053902008041000000c002200210000000000121019f0000000002090019000300000009001d14de14d40000040f0000000309000029000000010220018f00030000000103550000006001100270000105390010019d0000053901100197000000000001004b000012d80000c13d000000600b000039000000800a00003900000000010b0433000000000002004b0000134c0000613d000000000001004b000013370000c13d00020000000b001d00010000000a001d00000598010000410000000000100443000300000009001d00000004009004430000000001000414000005390010009c0000053901008041000000c00110021000000599011001c7000080020200003914de14d90000040f00000001002001900000135f0000613d000000000101043b000000000001004b0000000201000029000013600000613d0000000001010433000000000001004b0000000309000029000000010a000029000013430000613d000005d40010009c0000134a0000213d000000200010008c0000134a0000413d00000000010a0433000000000001004b0000000002000039000000010200c039000000000021004b0000134a0000c13d000000000001004b000013520000613d000000000001042d000005bc01000041000000000010043f0000004101000039000000040010043f0000054201000041000014e0000104300000000001000019000014e000010430000000000001004b000013570000c13d000005d701000041000000000010043f0000059701000041000014e000010430000005d501000041000000000010043f000000040090043f0000054201000041000014e0000104300000053900a0009c000005390a0080410000004002a00210000005390010009c00000539010080410000006001100210000000000121019f000014e000010430000000000001042f000005d601000041000000000010043f0000000301000029000000040010043f0000054201000041000014e0000104300007000000000002000600000002001d000700000001001d000000000010043f0000000901000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000014030000613d000000000101043b00000006020000290000053c02200197000000000020043f000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000014030000613d000000000101043b000600000001001d0000000801000039000000000201041a0000000703000029000000000032004b000014050000a13d000000000010043f0000000a013000c90000001302000039000000000202041a000300000002001d000005890210009a000000000202041a000200000002001d0000058a0210009a000000000202041a000400000002001d0000058b0210009a000000000202041a000100000002001d0000058c0110009a000000000101041a000500000001001d0000058d0100004100000000001004430000000001000414000005390010009c0000053901008041000000c0011002100000058e011001c70000800b0200003914de14d90000040f00000001002001900000140b0000613d000000000101043b0000000206000029000000000061004b00000006040000290000000505000029000013eb0000a13d000000040000006b000013eb0000613d000000030000006b000013eb0000613d0000000b02000039000000000202041a000000000012004b00000000030100190000000003024019000000000002004b000000000103c019000000000261004b0000000003000019000013c80000a13d0000058f012000d100000000022100d90000058f0020009c000013fd0000c13d000000000001004b000013c70000613d0000000702000039000000000202041a00000000031200a900000000011300d9000000000021004b000013c80000613d000013fd0000013d0000000003000019000200000003001d0000000701000029000000000010043f0000001201000039000000200010043f0000000001000414000005390010009c0000053901008041000000c00110021000000588011001c7000080100200003914de14d90000040f0000000100200190000014030000613d000000000101043b000000000201041a000000020300002900000000013200a9000000000003004b00000006040000290000000505000029000013e10000613d00000000033100d9000000000023004b000013fd0000c13d000000010200008a000000010220014f00000003011000fa0000058f0310012a000000000023004b000013fd0000213d00000004011000fa000000000051001a000013fd0000413d0000000005510019000000000204041a00000000015200a9000000000002004b000013f20000613d00000000022100d9000000000052004b000013fd0000c13d0000058f0110012a0000000302400039000000000202041a000000000012001a000013fd0000413d00000000011200190000000402400039000000000202041a000000000121004b000013fd0000413d000000000001042d000005bc01000041000000000010043f0000001101000039000000040010043f0000054201000041000014e0000104300000000001000019000014e000010430000005bc01000041000000000010043f0000003201000039000000040010043f0000054201000041000014e000010430000000000001042f0003000000000002000000003402043400000000020004140000053c09100197000000040090008c000014400000c13d00000001020000390000000101000031000000000001004b000014560000613d000005ba0010009c000014840000813d0000001f04100039000005ce044001970000003f04400039000005ce04400197000000400b00043d00000000044b00190000000000b4004b00000000050000390000000105004039000005840040009c000014840000213d0000000100500190000014840000c13d000000400040043f000000000a1b0436000005ce031001980000001f0410018f00000000013a00190000000305000367000014320000613d000000000605034f00000000070a0019000000006806043c0000000007870436000000000017004b0000142e0000c13d000000000004004b000014580000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000014580000013d000005390040009c00000539040080410000006001400210000005390030009c00000539030080410000004003300210000000000131019f000005390020009c0000053902008041000000c002200210000000000121019f0000000002090019000300000009001d14de14d40000040f0000000309000029000000010220018f00030000000103550000006001100270000105390010019d0000053901100197000000000001004b000014160000c13d000000600b000039000000800a00003900000000010b0433000000000002004b0000148a0000613d000000000001004b000014750000c13d00020000000b001d00010000000a001d00000598010000410000000000100443000300000009001d00000004009004430000000001000414000005390010009c0000053901008041000000c00110021000000599011001c7000080020200003914de14d90000040f00000001002001900000149d0000613d000000000101043b000000000001004b00000002010000290000149e0000613d0000000001010433000000000001004b0000000309000029000000010a000029000014810000613d000005d40010009c000014820000213d000000200010008c000014820000413d00000000010a0433000000000001004b0000000002000039000000010200c039000000000021004b000014820000c13d000000000001004b000014900000613d000000000001042d0000000001000019000014e000010430000005bc01000041000000000010043f0000004101000039000000040010043f0000054201000041000014e000010430000000000001004b000014950000c13d000005d701000041000000000010043f0000059701000041000014e000010430000005d501000041000000000010043f000000040090043f0000054201000041000014e0000104300000053900a0009c000005390a0080410000004002a00210000005390010009c00000539010080410000006001100210000000000121019f000014e000010430000000000001042f000005d601000041000000000010043f0000000301000029000000040010043f0000054201000041000014e000010430000000000001042f000005390010009c000005390100804100000060011002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f0000053e011001c7000080100200003914de14d90000040f0000000100200190000014b40000613d000000000101043b000000000001042d0000000001000019000014e00001043000000000050100190000000000200443000000050030008c000014c40000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b000014bc0000413d000005390030009c000005390300804100000060013002100000000002000414000005390020009c0000053902008041000000c002200210000000000112019f000005d8011001c7000000000205001914de14d90000040f0000000100200190000014d30000613d000000000101043b000000000001042d000000000001042f000014d7002104210000000102000039000000000001042d0000000002000019000000000001042d000014dc002104230000000102000039000000000001042d0000000002000019000000000001042d000014de00000432000014df0001042e000014e00001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000008be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e000000002000000000000000000000000000000c00000010000000000000000001e4fbdf70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000000000000000000000000000000000078d849ec00000000000000000000000000000000000000000000000000000000b092145d00000000000000000000000000000000000000000000000000000000e198a86200000000000000000000000000000000000000000000000000000000eaac8c3100000000000000000000000000000000000000000000000000000000fb8d81f000000000000000000000000000000000000000000000000000000000fb8d81f100000000000000000000000000000000000000000000000000000000fff52ee800000000000000000000000000000000000000000000000000000000eaac8c3200000000000000000000000000000000000000000000000000000000f2fde38b00000000000000000000000000000000000000000000000000000000e198a86300000000000000000000000000000000000000000000000000000000e30c397800000000000000000000000000000000000000000000000000000000e78cea9200000000000000000000000000000000000000000000000000000000d4c3ee9f00000000000000000000000000000000000000000000000000000000d4c3eea000000000000000000000000000000000000000000000000000000000d69efdc500000000000000000000000000000000000000000000000000000000de26c3c600000000000000000000000000000000000000000000000000000000b092145e00000000000000000000000000000000000000000000000000000000bd35dd9200000000000000000000000000000000000000000000000000000000beece24b0000000000000000000000000000000000000000000000000000000093f1a40a00000000000000000000000000000000000000000000000000000000a04a4d5200000000000000000000000000000000000000000000000000000000a04a4d5300000000000000000000000000000000000000000000000000000000a8a77a1900000000000000000000000000000000000000000000000000000000ad88a17e0000000000000000000000000000000000000000000000000000000093f1a40b0000000000000000000000000000000000000000000000000000000099d8f74a00000000000000000000000000000000000000000000000000000000a01892a500000000000000000000000000000000000000000000000000000000885dba1c00000000000000000000000000000000000000000000000000000000885dba1d000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000933f39580000000000000000000000000000000000000000000000000000000078d849ed0000000000000000000000000000000000000000000000000000000079ba5097000000000000000000000000000000000000000000000000000000007a94c06800000000000000000000000000000000000000000000000000000000396f7b2200000000000000000000000000000000000000000000000000000000606ce3be000000000000000000000000000000000000000000000000000000006e910bfc000000000000000000000000000000000000000000000000000000006e910bfd000000000000000000000000000000000000000000000000000000006f52daaf00000000000000000000000000000000000000000000000000000000715018a600000000000000000000000000000000000000000000000000000000606ce3bf00000000000000000000000000000000000000000000000000000000630b5ba1000000000000000000000000000000000000000000000000000000006b1033c400000000000000000000000000000000000000000000000000000000441a3e6f00000000000000000000000000000000000000000000000000000000441a3e70000000000000000000000000000000000000000000000000000000005c60da1b0000000000000000000000000000000000000000000000000000000060246c8800000000000000000000000000000000000000000000000000000000396f7b23000000000000000000000000000000000000000000000000000000003fdb1e8f0000000000000000000000000000000000000000000000000000000042cbb15c0000000000000000000000000000000000000000000000000000000017caf6f00000000000000000000000000000000000000000000000000000000026076f960000000000000000000000000000000000000000000000000000000026076f97000000000000000000000000000000000000000000000000000000002d25a23d0000000000000000000000000000000000000000000000000000000030cdb3c60000000000000000000000000000000000000000000000000000000017caf6f1000000000000000000000000000000000000000000000000000000001abbeb54000000000000000000000000000000000000000000000000000000001e1c6a070000000000000000000000000000000000000000000000000000000012863f010000000000000000000000000000000000000000000000000000000012863f02000000000000000000000000000000000000000000000000000000001526fe270000000000000000000000000000000000000000000000000000000015ba56e50000000000000000000000000000000000000000000000000000000000aeef8a00000000000000000000000000000000000000000000000000000000081e3eda00000000000000000000000000000000000000000000000000000000083c6323000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000000000000000000000000000000000000000000ffffffffffffff7f00000000000000000000000000000000000000000000003fffffffffffffffe002000000000000000000000000000000000000400000000000000000000000000c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c91170c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c911b0c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c91150c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c911642cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd102000002000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000de0b6b3a7640000118cdaa70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003627e8f712373c0000b48e36a0869514773506a41441177faf21ebdda362731b7363ee174f3a00772838d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008da5cb5b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000080000000000000000082b429000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b83020000020000000000000000000000000000002400000000000000000000000015ba56e5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000800000000000000000310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0200000200000000000000000000000000000044000000000000000000000000f84de9bf00000000000000000000000000000000000000000000000000000000496e76616c696420706f6f6c206964000000000000000000000000000000000008c379a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006400000000000000000000000062616c616e63657320646f6e2774206d61746368000000000000000000000000000000000000000000000000000000000000002000000000000000000000000067f679e13fe9dca16f3079221965ec41838cb8881cbc0f440bc13507c6b214c20c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c911d0200000000000000000000000000000000000020000000000000000000000000845324a5e5310b4f56edb5ef034fb84a1a21fb9248f15eb3ad2d205f7f8f2d60af5e9d9d00000000000000000000000000000000000000000000000000000000f48e3c2600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffebf0c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c911c0c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c911a0c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c91190c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c91180c085601c9b05546c4de925af5cdebeab0dd5f5d4bea4dc57b37e961749c9114c264f49177bdbe55a01fae0e77c3fdc75d515d242b32bc4d56c565f5b47865bad92e233d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000800000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5f00000000000000000000000000000000000000a00000008000000000000000008000000000000000000000000000000000000000000000000000000000000000ea0f55620000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003627e8f712373c0001ede31886000000000000000000000000000000000000000000000000000000009eca8f7bcfb868d72b4ed95b71c627c194ab6bcb9b83adb2280e8a0320bb84760000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000fffffffffffffe3f4e487b710000000000000000000000000000000000000000000000000000000015e34e0500000000000000000000000000000000000000000000000000000000bc53949c00000000000000000000000000000000000000000000000000000000f279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568214671ad000000000000000000000000000000000000000000000000000000001e110c234a3519983cc1a5dc771c3648cfb2118072924b096d56566097b2251b061008d1000000000000000000000000000000000000000000000000000000000e2d25f1d1094599e7ad7c5abf20c243dd116941d455eb79616135defbc6fb9b9c8787c0000000000000000000000000000000000000000000000000000000002f352531000000000000000000000000000000000000000000000000000000008cd22d19000000000000000000000000000000000000000000000000000000007bd4747600000000000000000000000000000000000000000000000000000000eb7a7d62743daf8cf4055aea544d0a89e2011279ed4105567d010759e6fa4de223b872dd00000000000000000000000000000000000000000000000000000000442400af0000000000000000000000000000000000000000000000000000000036af321ec8d3c75236829c5317affd40ddb308863a1236d2d277a4025cccee1eb2e532de00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff41976e090000000000000000000000000000000000000000000000000000000017b8644f386d1c7c7138ef98b3c8035622bbe94d7be9b26f71d2654a547c2943a9059cbb00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff5274afe7000000000000000000000000000000000000000000000000000000009996b315000000000000000000000000000000000000000000000000000000001425ea42000000000000000000000000000000000000000000000000000000000200000200000000000000000000000000000000000000000000000000000000
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a24f69faa295426bca2cf610bf992cdc992ceea00000000000000000000000002edf18b640a705f16947a7b95fc338fde340dd48
-----Decoded View---------------
Arg [0] : _MERKLE (address): 0xa24F69fAA295426Bca2Cf610bf992CDc992CeEa0
Arg [1] : _priceFeeds (address): 0x2eDf18b640A705F16947A7B95Fc338fde340Dd48
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000a24f69faa295426bca2cf610bf992cdc992ceea0
Arg [1] : 0000000000000000000000002edf18b640a705f16947a7b95fc338fde340dd48
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.