Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 16572139 | 538 days ago | IN | 0 ETH | 0.02597423 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
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 Name:
BaseV2GaugeFactory
Compiler Version
v0.8.11+commit.d7f03943
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.11; import "./ProxyPattern/SolidlyFactory.sol"; import "./ProxyPattern/SolidlyChildImplementation.sol"; library Math { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } } interface erc20 { function totalSupply() external view returns (uint256); function transfer(address recipient, uint256 amount) external returns (bool); function balanceOf(address) external view returns (uint256); function transferFrom( address sender, address recipient, uint256 amount ) external returns (bool); function approve(address spender, uint256 value) external returns (bool); } interface IVeV2 { function token() external view returns (address); function balanceOfNFT(uint256) external view returns (uint256); function isApprovedOrOwner(address, uint256) external view returns (bool); function ownerOf(uint256) external view returns (address); function transferFrom( address, address, uint256 ) external; } interface IBaseV2Factory { function isPair(address) external view returns (bool); } interface IBaseV2Pair { function claimFees() external returns (uint256, uint256); function tokens() external returns (address, address); } interface IBribeV2 { function notifyRewardAmount(address token, uint256 amount) external; function left(address token) external view returns (uint256); } interface IVoterV2 { function attachTokenToGauge(uint256 _tokenId, address account) external; function detachTokenFromGauge(uint256 _tokenId, address account) external; function generalFees() external view returns (address); function emitDeposit( uint256 _tokenId, address account, uint256 amount ) external; function emitWithdraw( uint256 _tokenId, address account, uint256 amount ) external; function distribute(address _gauge) external; function feeDists(address _pool) external view returns (address _feeDist); } interface IFeeDistV2 { function claimFees() external; } interface IBaseV2GeneralFees { function notifyRewardAmount(address token, uint256 amount) external; } // Gauges are used to incentivize pools, they emit reward tokens over 7 days for staked LP tokens /** * @dev Changelog: * - Deprecate constructor with initialize() * - Deprecate checkpoint and indexing system, replaced with opt-in multirewards like system * - Uses RewardRatePerWeek instead of RewardRate for reward calculations (better precision) * - Adapt _claimFees() to support transfer tax tokens * - Immutable storage slots became mutable but made sure nothing changes them after initialize() * - No longer calls voter to emit deposit and withdrawal */ contract GaugeV2 is SolidlyChildImplementation { uint256 internal constant DURATION = 7 days; // rewards are released over 7 days uint256 internal constant PRECISION = 10**44; /** * @dev storage slots start here */ // simple re-entrancy check uint256 internal _unlocked = 1; address public stake; // the LP token that needs to be staked for rewards address public _ve; // the ve token used for gauges address public solid; address public bribe; address public voter; uint256 public derivedSupply; mapping(address => uint128) public derivedBalances; mapping(address => uint256) public tokenIds; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => bool)) public isOptIn; // userAddress => rewardAddress => bool mapping(address => address[]) public userOptIns; // array of rewards the user is opted into mapping(address => mapping(address => uint256)) public userOptInsIndex; // index of pools within userOptIns userAddress =>rewardAddress => index // default snx staking contract implementation mapping(address => RewardData) public rewardData; struct RewardData { uint128 rewardRatePerWeek; uint128 derivedSupply; uint256 rewardPerTokenStored; uint40 periodFinish; uint40 lastUpdateTime; } struct UserRewardData { uint256 userRewardPerTokenPaid; uint256 userEarnedStored; } mapping(address => mapping(address => UserRewardData)) public userRewardData; // userAddress => tokenAddress => userRewardData uint256 public totalSupply; address[] public rewards; mapping(address => bool) public isReward; uint256 public fees0; uint256 public fees1; event Deposit(address indexed from, uint256 tokenId, uint256 amount); event OptIn(address indexed from, address indexed reward); event OptOut(address indexed from, address indexed reward); event Withdraw(address indexed from, uint256 tokenId, uint256 amount); event NotifyReward( address indexed from, address indexed reward, uint256 amount ); event ClawbackRewards(address indexed reward, uint256 amount); event ClaimFees(address indexed from, uint256 claimed0, uint256 claimed1); event ClaimRewards( address indexed from, address indexed reward, uint256 amount ); // simple re-entrancy check modifier lock() { require(_unlocked == 1); _unlocked = 2; _; _unlocked = 1; } function initialize( address _stake, address _bribe, address __ve, address _voter ) external onlyFactory notInitialized { _unlocked = 1; stake = _stake; bribe = _bribe; _ve = __ve; voter = _voter; solid = IVeV2(_ve).token(); } /**************************************** View Methods ****************************************/ /** * @notice Returns the balance derived based on veToken staked. Used to determine ratio of rewards streamed * @param account User address */ function derivedBalance(address account) public view returns (uint256) { if (BaseV2GaugeFactory(factoryAddress()).isBoostPaused()) { return balanceOf[account]; } else { uint256 _tokenId = tokenIds[account]; uint256 _balance = balanceOf[account]; uint256 _derived = (_balance * 40) / 100; uint256 _adjusted = 0; uint256 _supply = erc20(_ve).totalSupply(); if (account == IVeV2(_ve).ownerOf(_tokenId) && _supply > 0) { _adjusted = IVeV2(_ve).balanceOfNFT(_tokenId); _adjusted = (((totalSupply * _adjusted) / _supply) * 60) / 100; } return Math.min((_derived + _adjusted), _balance); } } /** * @dev ATTENTION ordering is flipped to (token, account) instead of (account, token) for backwards compatibility */ function earned(address token, address account) external view returns (uint256) { RewardData memory _rewardData = rewardData[token]; UserRewardData memory _userRewardData = userRewardData[account][token]; uint256 _earned = _userRewardData.userEarnedStored; if (isOptIn[account][token]) { _earned += ((derivedBalances[account] * (_rewardPerToken(_rewardData) - _userRewardData.userRewardPerTokenPaid)) / PRECISION); } return _earned; } /** * @notice Internal view method does not call _rewardPerToken() since it's always updated just before this is called * @dev ATTENTION input orders are (account, token) to comform with RewardData structures */ function _earnedFromStored(address account, address token) internal view returns (uint256) { UserRewardData memory _userRewardData = userRewardData[account][token]; uint256 _earned = (_userRewardData.userEarnedStored) + ((derivedBalances[account] * (rewardData[token].rewardPerTokenStored - _userRewardData.userRewardPerTokenPaid)) / PRECISION); return _earned; } /** * @notice Returns the last time the reward was modified or periodFinish if the reward has ended */ function lastTimeRewardApplicable(address token) external view returns (uint256) { return Math.min(block.timestamp, rewardData[token].periodFinish); } /** * @notice View method for backwards compatibility * @dev Now part of RewardData struct * @param token Reward token */ function lastUpdateTime(address token) external view returns (uint256) { return rewardData[token].lastUpdateTime; } /** * @notice Returns the amount of rewards left in the reward period * @param token Reward token */ function left(address token) external view returns (uint256) { RewardData memory _rewardData = rewardData[token]; if (block.timestamp >= _rewardData.periodFinish) { return 0; } uint256 _remaining = _rewardData.periodFinish - block.timestamp; return (_remaining * _rewardData.rewardRatePerWeek) / DURATION; } /** * @notice View method for backwards compatibility * @dev Now part of RewardData struct * @param token Reward token */ function periodFinish(address token) external view returns (uint256) { return rewardData[token].periodFinish; } /** * @notice View method for backwards compatibility * @dev Now part of RewardData struct * @param token Reward token */ function rewardPerTokenStored(address token) external view returns (uint256) { return rewardData[token].rewardPerTokenStored; } /** * @notice View method for backwards compatibility * @dev rewardRate decprecated in favour of rewardRatePerWeek since DURATION is constant * @param token Reward token */ function rewardRate(address token) external view returns (uint256) { return rewardData[token].rewardRatePerWeek / DURATION; } /** * @notice Returns the rewardsList length */ function rewardsListLength() external view returns (uint256) { return rewards.length; } /** * @notice Backwards compatible wiew method for rewardPerToken * @param token Reward token */ function rewardPerToken(address token) external view returns (uint256) { RewardData memory _rewardData = rewardData[token]; return _rewardPerToken(_rewardData); } /** * @notice view method for rewardPerToken * @dev passing RewardData instead of tokenAddress to save gas on SLOAD * @param _rewardData RewardData struct for the reward token */ function _rewardPerToken(RewardData memory _rewardData) internal view returns (uint256) { if (_rewardData.derivedSupply == 0) { return _rewardData.rewardPerTokenStored; } uint256 timeElapsed = (Math.min( block.timestamp, _rewardData.periodFinish ) - Math.min(_rewardData.lastUpdateTime, _rewardData.periodFinish)); return _rewardData.rewardPerTokenStored + uint256( ((((PRECISION / DURATION) * _rewardData.rewardRatePerWeek) / _rewardData.derivedSupply) * timeElapsed) ); } /** * @notice Backwards compatible wiew method for userRewardPerTokenStored * @dev ATTENTION input ordering is (token, account) for backwards compatibility * @param token Reward token * @param account User address */ function userRewardPerTokenStored(address token, address account) external view returns (uint256) { return userRewardData[account][token].userRewardPerTokenPaid; } /**************************************** Protocol Interaction ****************************************/ /** * @notice Calls the feeDist to claimFees from the pair * @dev Kept for backwards compatibility */ function claimFees() external returns (uint256 claimed0, uint256 claimed1) { // Fetch addresses address _feeDist = IVoterV2(voter).feeDists(stake); address[] memory tokens = new address[](2); (tokens[0], tokens[1]) = IBaseV2Pair(stake).tokens(); // Fetch current status uint256[] memory balancesBefore = new uint256[](2); balancesBefore[0] = erc20(tokens[0]).balanceOf(_feeDist); balancesBefore[1] = erc20(tokens[1]).balanceOf(_feeDist); // Call feeDist to claim fees IFeeDistV2(_feeDist).claimFees(); // Compute claimed amounts claimed0 = erc20(tokens[0]).balanceOf(_feeDist) - balancesBefore[0]; claimed1 = erc20(tokens[1]).balanceOf(_feeDist) - balancesBefore[1]; return (claimed0, claimed1); } /**************************************** User Interaction ****************************************/ modifier updateReward(address account) { uint128 _derivedBalance = derivedBalances[account]; uint256 _balanceOf = balanceOf[account]; for (uint256 i; i < userOptIns[account].length; i++) { address token = userOptIns[account][i]; RewardData memory _rewardData = rewardData[token]; // gas savings _rewardData.rewardPerTokenStored = _rewardPerToken(_rewardData); _rewardData.lastUpdateTime = uint40( Math.min(block.timestamp, _rewardData.periodFinish) ); // reduce derivedBalance for opted in pools, readjust them later rewardData[token] = _rewardData; UserRewardData memory _userRewardData = userRewardData[account][ token ]; uint256 _earnedBefore = _userRewardData.userEarnedStored; uint256 _earnedAfter = _earnedFromStored(account, token); // only update userRewardPerTokenPaid if earned goes up, // but if derivedBalance changes, update regardless (code at the end of modifier) if (_earnedAfter > _earnedBefore) { userRewardData[account][token].userEarnedStored = _earnedAfter; userRewardData[account][token] .userRewardPerTokenPaid = rewardData[token] .rewardPerTokenStored; } } _; // update balance uint128 _derivedBalanceBefore = _derivedBalance; uint256 _derivedSupply = derivedSupply; _derivedSupply -= _derivedBalanceBefore; _derivedBalance = uint128(derivedBalance(account)); derivedBalances[account] = _derivedBalance; _derivedSupply += _derivedBalance; derivedSupply = _derivedSupply; // Update derivedBalances for the opted-in pools for (uint256 i; i < userOptIns[account].length; i++) { address token = userOptIns[account][i]; uint128 _derivedSupply = rewardData[token].derivedSupply; _derivedSupply -= _derivedBalanceBefore; _derivedSupply += _derivedBalance; rewardData[token].derivedSupply = _derivedSupply; } // update userRewardPerTokenPaid anyways if derivedBalance changes if (_derivedBalanceBefore != _derivedBalance) { for (uint256 i; i < userOptIns[account].length; i++) { address token = userOptIns[account][i]; userRewardData[account][token] .userRewardPerTokenPaid = rewardData[token] .rewardPerTokenStored; } } } /** * @notice Deposits all LP tokens into the gauge, opts into solid pool by default if not already opted-in * @param tokenId The veNFT tokenId to associate with the user */ function depositAll(uint256 tokenId) external { deposit(erc20(stake).balanceOf(msg.sender), tokenId); } /** * @notice Deposits LP tokens into the gauge, opts into solid pool by default if not already opted-in * @param amount Amount to deposit * @param tokenId The veNFT tokenId to associate with the user */ function deposit(uint256 amount, uint256 tokenId) public { address _solid = solid; // opt-in to solid and the 2 base tokens if not already opted into solid if (!isOptIn[msg.sender][_solid]) { address[] memory _optInPools = new address[](3); (address _token0, address _token1) = IBaseV2Pair(stake).tokens(); _optInPools[0] = _solid; _optInPools[1] = _token0; _optInPools[2] = _token1; depositAndOptIn(amount, tokenId, _optInPools); } else { depositAndOptIn(amount, tokenId, new address[](0)); } } /** * @notice Deposits LP tokens into the gauge, opts into pools specified if not already opted-in * @param amount Amount to deposit * @param tokenId The veNFT tokenId to associate with the user * @param optInPools The reward pools to opt-in to */ function depositAndOptIn( uint256 amount, uint256 tokenId, address[] memory optInPools ) public lock updateReward(msg.sender) { require(amount > 0, "Cannot deposit 0"); _safeTransferFrom(stake, msg.sender, address(this), amount); totalSupply += amount; balanceOf[msg.sender] += amount; if (tokenId > 0) { require(IVeV2(_ve).ownerOf(tokenId) == msg.sender, "tokenId auth"); if (tokenIds[msg.sender] == 0) { tokenIds[msg.sender] = tokenId; IVoterV2(voter).attachTokenToGauge(tokenId, msg.sender); } require( tokenIds[msg.sender] == tokenId, "Different tokenId already attached" ); } else { tokenId = tokenIds[msg.sender]; } for (uint256 i = 0; i < optInPools.length; i++) { if (!isOptIn[msg.sender][optInPools[i]]) { _optIn(optInPools[i]); } } emit Deposit(msg.sender, tokenId, amount); } /** * @notice Opt-in to the specified reward pools * @dev Updates reward pools before hand because this is like a balance change for the pool * @param tokens The reward pools to opt-in to */ function optIn(address[] calldata tokens) external lock updateReward(msg.sender) { for (uint256 i = 0; i < tokens.length; i++) { // Taking out checks for isReward allows people to opt-into pools before they start, // which might be benefitial if projects announce rewards in advance, // makes things fairer too. if (!isOptIn[msg.sender][tokens[i]]) { _optIn(tokens[i]); } } } /** * @notice Internal function for optIn() * @param token The reward pool to opt-in to */ function _optIn(address token) internal { RewardData memory _rewardData = rewardData[token]; _rewardData.derivedSupply += derivedBalances[msg.sender]; _rewardData.rewardPerTokenStored = _rewardPerToken(_rewardData); _rewardData.lastUpdateTime = uint40( Math.min(block.timestamp, _rewardData.periodFinish) ); rewardData[token] = _rewardData; UserRewardData memory _userRewardData = UserRewardData({ userRewardPerTokenPaid: _rewardData.rewardPerTokenStored, userEarnedStored: 0 }); userRewardData[msg.sender][token] = _userRewardData; isOptIn[msg.sender][token] = true; userOptInsIndex[msg.sender][token] = userOptIns[msg.sender].length; userOptIns[msg.sender].push(token); emit OptIn(msg.sender, token); } /** * @notice Opt-out of the specified reward pools * @dev This method updates the reward pools beforehand, storing all user earned amounts for later claiming * @param tokens The reward pools to opt-out of */ function optOut(address[] calldata tokens) external lock updateReward(msg.sender) { // Actually doesn't really matter if the user has unclaimed rewards // since it updates all rewards in the modifier and users can claim // stored rewards even after opting out for (uint256 i = 0; i < tokens.length; i++) { if (isOptIn[msg.sender][tokens[i]]) { _optOut(tokens[i]); } } } /** * @notice skips updateReward(). Forfeits all unstored accrued rewards for the selected pools. Only useful when a user enters too many pools */ function emergencyOptOut(address[] calldata tokens) external lock { for (uint256 i = 0; i < tokens.length; i++) { uint128 _derivedBalance = derivedBalances[msg.sender]; if (isOptIn[msg.sender][tokens[i]]) { rewardData[tokens[i]].derivedSupply -= _derivedBalance; _optOut(tokens[i]); } } } /** * @notice Internal function for optOut() and emergencyOptOut() * @param token The reward pool to opt-in to */ function _optOut(address token) internal { isOptIn[msg.sender][token] = false; uint256 index = userOptInsIndex[msg.sender][token]; delete userOptInsIndex[msg.sender][token]; // Delete index for tokenId // Fetch last opt-in in array address lastOptIn = userOptIns[msg.sender][ userOptIns[msg.sender].length - 1 ]; userOptIns[msg.sender][index] = lastOptIn; // Update userOptIns userOptInsIndex[msg.sender][lastOptIn] = index; // Update index by token ID userOptIns[msg.sender].pop(); // Remove last userOptIn emit OptOut(msg.sender, token); } function withdrawAll() external { withdraw(balanceOf[msg.sender]); } /** * @notice Withdraws LP tokens, and detaches veNFT from the gauge final balance becomes 0 * @param amount The amount of LP to withdraw */ function withdraw(uint256 amount) public { uint256 tokenId = 0; if (amount == balanceOf[msg.sender]) { tokenId = tokenIds[msg.sender]; } withdrawToken(amount, tokenId); } /** * @notice Withdraws LP tokens, and detaches veNFT from the gauge if specified * @param amount The amount of LP to withdraw * @param tokenId The veNFT to detach, input 0 to skip detachment */ function withdrawToken(uint256 amount, uint256 tokenId) public lock updateReward(msg.sender) { totalSupply -= amount; balanceOf[msg.sender] -= amount; _safeTransfer(stake, msg.sender, amount); if (tokenId > 0) { require(tokenId == tokenIds[msg.sender], "tokenId auth"); tokenIds[msg.sender] = 0; IVoterV2(voter).detachTokenFromGauge(tokenId, msg.sender); } else { tokenId = tokenIds[msg.sender]; } emit Withdraw(msg.sender, tokenId, amount); } function getReward(address account, address[] memory tokens) external lock updateReward(account) { require( msg.sender == account || msg.sender == voter, "msg.sender not account" ); _unlocked = 1; IVoterV2(voter).distribute(address(this)); _unlocked = 2; for (uint256 i = 0; i < tokens.length; i++) { uint256 _reward = userRewardData[account][tokens[i]] .userEarnedStored; if (_reward > 0) { // only need to look at stored amounts because updateReward() is called beforehand userRewardData[account][tokens[i]].userEarnedStored = 0; _safeTransfer(tokens[i], account, _reward); } emit ClaimRewards(msg.sender, tokens[i], _reward); } } function notifyRewardAmount(address token, uint256 amount) external lock { require(token != stake, "Invalid reward token"); require(amount > 0, "Cannot notify 0"); require(amount < type(uint128).max, "too much amount"); uint128 amount = uint128(amount); RewardData memory _rewardData = rewardData[token]; // gas savings // update pool first _rewardData.rewardPerTokenStored = _rewardPerToken(_rewardData); _rewardData.lastUpdateTime = uint40( Math.min(block.timestamp, _rewardData.periodFinish) ); // fetch current balance uint256 balanceBefore = erc20(token).balanceOf(address(this)); // transfer tokens, recalculate amount in case of transfer-tax _safeTransferFrom(token, msg.sender, address(this), amount); amount = uint128(erc20(token).balanceOf(address(this)) - balanceBefore); if (block.timestamp >= _rewardData.periodFinish) { _rewardData.rewardRatePerWeek = amount; } else { uint40 _remaining = _rewardData.periodFinish - uint40(block.timestamp); uint128 _left = uint128( (_remaining * _rewardData.rewardRatePerWeek) / DURATION ); require(amount > _left || msg.sender == voter, "amount < left"); _rewardData.rewardRatePerWeek = amount + _left; } require(_rewardData.rewardRatePerWeek > 0, "rewardRate too low"); uint256 balance = erc20(token).balanceOf(address(this)); require( _rewardData.rewardRatePerWeek <= balance, "Not enough tokens provided" ); _rewardData.periodFinish = uint40(block.timestamp + DURATION); _rewardData.lastUpdateTime = uint40(block.timestamp); rewardData[token] = _rewardData; if (!isReward[token]) { isReward[token] = true; rewards.push(token); } emit NotifyReward(msg.sender, token, amount); } // Be VERY CAREFUL when using this, gauge does not track how much reward // is supposed to be in the contract, since it'll take too much gas // to record balance changes on every interaction just for the next to // 0 possibility that this function is used // Off-chain calculations should be double-checked before using this function function clawbackRewards(address token, uint256 amount) external onlyGovernance { require(token != stake, "Cannot clawback LP"); require(amount > 0, "Cannot clawback 0"); address generalFeesAddress = IVoterV2(voter).generalFees(); // Approve amount and notifyReward for generalFees _safeApprove(token, generalFeesAddress, amount); IBaseV2GeneralFees(generalFeesAddress).notifyRewardAmount( token, amount ); emit ClawbackRewards(token, amount); } /**************************************** SafeERC20 ****************************************/ function _safeTransfer( address token, address to, uint256 value ) internal { require(token.code.length > 0, "!contract"); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(erc20.transfer.selector, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: safeTransfer low-level call failed" ); } function _safeTransferFrom( address token, address from, address to, uint256 value ) internal { require(token.code.length > 0, "!contract"); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(erc20.transferFrom.selector, from, to, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: safeTransferFrom low-level call failed" ); } function _safeApprove( address token, address spender, uint256 value ) internal { require(token.code.length > 0, "!contract"); (bool success, bytes memory data) = token.call( abi.encodeWithSelector(erc20.approve.selector, spender, value) ); require( success && (data.length == 0 || abi.decode(data, (bool))), "SafeERC20: approve low-level call failed" ); } } /** * @dev Changelog: * - Deprecate createGaugeSingle() * - Deprecate last_gauge; * - Refactored createGauge(); */ contract BaseV2GaugeFactory is SolidlyFactory { bool public isBoostPaused; function createGauge( address _pool, address _bribe, address _ve ) external returns (address lastGauge) { lastGauge = _deployChildProxy(); GaugeV2(lastGauge).initialize(_pool, _bribe, _ve, msg.sender); return lastGauge; } function setBoostPaused(bool _state) external onlyGovernance { isBoostPaused = _state; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.11; import "./SolidlyImplementation.sol"; import "./interfaces/IFactory.sol"; contract SolidlyChildImplementation is SolidlyImplementation { bytes32 constant FACTORY_SLOT = 0x547b500e425d72fd0723933cceefc203cef652b4736fd04250c3369b3e1a0a72; // keccak256('FACTORY') - 1 modifier onlyFactory() { require(msg.sender == factoryAddress(), "only Factory"); _; } /**************************************** VIEW METHODS ****************************************/ /** * @notice Fetch current governance address from factory * @return _governanceAddress Returns current governance address */ function governanceAddress() public view override returns (address _governanceAddress) { return IFactory(factoryAddress()).governanceAddress(); } function factoryAddress() public view returns (address _factory) { assembly { _factory := sload(FACTORY_SLOT) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.11; import "./SolidlyImplementation.sol"; import "./SolidlyChildProxy.sol"; contract SolidlyFactory is SolidlyImplementation { bytes32 constant CHILD_SUBIMPLEMENTATION_SLOT = 0xa7461aa7cde97eb2572f8234e341359c6baae47e1feeb3c235edffe5f0fc089d; // keccak256('CHILD_SUBIMPLEMENTATION') - 1 bytes32 constant CHILD_INTERFACE_SLOT = 0x23762bb6469fe7a7bd6609262f442817ed09ca1f07add24ef069610d59c90649; // keccak256('CHILD_INTERFACE') - 1 bytes32 constant SUBIMPLEMENTATION_SLOT = 0xa1056f3ed783ff191ada02861fcb19d9ae3a8f50b739813a127951ef5290458d; // keccak256('SUBIMPLEMENTATION') - 1 bytes32 constant INTERFACE_SLOT = 0x4a9bf2931aa5eae439c602abae4bd662e7919244decac463e2e35fc862c5fb98; // keccak256('INTERFACE') - 1 address public interfaceSourceAddress; function _deployChildProxy() internal returns (address) { address addr = address(new SolidlyChildProxy()); return addr; } function _deployChildProxyWithSalt(bytes32 salt) internal returns (address) { address addr = address(new SolidlyChildProxy{salt: salt}()); return addr; } function updateChildSubImplementationAddress( address _childSubImplementationAddress ) external onlyGovernance { assembly { sstore(CHILD_SUBIMPLEMENTATION_SLOT, _childSubImplementationAddress) } } function updateChildInterfaceAddress(address _childInterfaceAddress) external onlyGovernance { assembly { sstore(CHILD_INTERFACE_SLOT, _childInterfaceAddress) } } function childSubImplementationAddress() external view returns (address _childSubImplementation) { assembly { _childSubImplementation := sload(CHILD_SUBIMPLEMENTATION_SLOT) } } function childInterfaceAddress() external view returns (address _childInterface) { assembly { _childInterface := sload(CHILD_INTERFACE_SLOT) } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.11; import "./SolidlyProxy.sol"; import "./interfaces/IFactory.sol"; /** * @notice Child Proxy deployed by factories for pairs, fees, gauges, and bribes. Calls back to the factory to fetch proxy implementation. */ contract SolidlyChildProxy is SolidlyProxy { bytes32 constant FACTORY_SLOT = 0x547b500e425d72fd0723933cceefc203cef652b4736fd04250c3369b3e1a0a72; // keccak256('FACTORY') - 1 modifier onlyFactory() { require(msg.sender == factoryAddress(), "only Factory"); _; } /** * @notice Records factory address and current interface implementation */ constructor() { address _factory = msg.sender; address _interface = IFactory(msg.sender).childInterfaceAddress(); assembly { sstore(FACTORY_SLOT, _factory) sstore(IMPLEMENTATION_SLOT, _interface) // Storing the interface into EIP-1967's implementation slot so Etherscan picks up the interface } } /**************************************** SETTINGS ****************************************/ /** * @notice Governance callable method to update the Factory address */ function updateFactoryAddress(address _factory) external onlyGovernance { assembly { sstore(FACTORY_SLOT, _factory) } } /** * @notice Publically callable function to sync proxy interface with the one recorded in the factory */ function updateInterfaceAddress() external { address _newInterfaceAddress = IFactory(factoryAddress()) .childInterfaceAddress(); require( implementationAddress() != _newInterfaceAddress, "Nothing to update" ); assembly { sstore(IMPLEMENTATION_SLOT, _newInterfaceAddress) } } /**************************************** VIEW METHODS ****************************************/ /** * @notice Fetch current governance address from factory * @return _governanceAddress Returns current governance address */ function governanceAddress() public view override returns (address _governanceAddress) { return IFactory(factoryAddress()).governanceAddress(); } function factoryAddress() public view returns (address _factory) { assembly { _factory := sload(FACTORY_SLOT) } } /** *@notice Fetch address where actual contract logic is at */ function subImplementationAddress() public view returns (address _subimplementation) { return IFactory(factoryAddress()).childSubImplementationAddress(); } /** * @notice Fetch address where the interface for the contract is */ function interfaceAddress() public view override returns (address _interface) { assembly { _interface := sload(IMPLEMENTATION_SLOT) } } /**************************************** FALLBACK METHODS ****************************************/ /** * @notice Fallback function that delegatecalls the subimplementation instead of what's in the IMPLEMENTATION_SLOT */ function _delegateCallSubimplmentation() internal override { address contractLogic = IFactory(factoryAddress()) .childSubImplementationAddress(); assembly { calldatacopy(0x0, 0x0, calldatasize()) let success := delegatecall( gas(), contractLogic, 0x0, calldatasize(), 0, 0 ) let returnDataSize := returndatasize() returndatacopy(0, 0, returnDataSize) switch success case 0 { revert(0, returnDataSize) } default { return(0, returnDataSize) } } } fallback() external payable override { _delegateCallSubimplmentation(); } receive() external payable override { _delegateCallSubimplmentation(); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.11; /** * @title Solidly+ Implementation * @author Solidly+ * @notice Governable implementation that relies on governance slot to be set by the proxy */ contract SolidlyImplementation { bytes32 constant GOVERNANCE_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; // keccak256('eip1967.proxy.admin') bytes32 constant INITIALIZED_SLOT = 0x834ce84547018237034401a09067277cdcbe7bbf7d7d30f6b382b0a102b7b4a3; // keccak256('eip1967.proxy.initialized') /** * @notice Reverts if msg.sender is not governance */ modifier onlyGovernance() { require(msg.sender == governanceAddress(), "Only governance"); _; } /** * @notice Reverts if contract is already initialized * @dev U4sed by implementations to ensure initialize() is only called once */ modifier notInitialized() { bool initialized; assembly { initialized := sload(INITIALIZED_SLOT) if eq(initialized, 1) { revert(0, 0) } sstore(INITIALIZED_SLOT, 1) } _; } /** * @notice Fetch current governance address * @return _governanceAddress Returns current governance address */ function governanceAddress() public view virtual returns (address _governanceAddress) { assembly { _governanceAddress := sload(GOVERNANCE_SLOT) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.11; interface IFactory { function governanceAddress() external view returns (address); function childSubImplementationAddress() external view returns (address); function childInterfaceAddress() external view returns (address); }
// SPDX-License-Identifier: BUSL pragma solidity 0.8.11; /** * @title Solidly+ governance killable proxy * @author Solidly+ * @notice EIP-1967 upgradeable proxy with the ability to kill governance and render the contract immutable */ contract SolidlyProxy { bytes32 constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; // keccak256('eip1967.proxy.implementation'), actually used for interface so etherscan picks up the interface bytes32 constant LOGIC_SLOT = 0x5942be825425c77e56e4bce97986794ab0f100954e40fc1390ae0e003710a3ab; // keccak256('LOGIC') - 1, actual logic implementation bytes32 constant GOVERNANCE_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; // keccak256('eip1967.proxy.admin') bytes32 constant INITIALIZED_SLOT = 0x834ce84547018237034401a09067277cdcbe7bbf7d7d30f6b382b0a102b7b4a3; // keccak256('eip1967.proxy.initialized') /** * @notice Reverts if msg.sender is not governance */ modifier onlyGovernance() { require(msg.sender == governanceAddress(), "Only governance"); _; } /** * @notice Reverts if contract is already initialized * @dev Used by implementations to ensure initialize() is only called once */ modifier notInitialized() { bool initialized; assembly { initialized := sload(INITIALIZED_SLOT) if eq(initialized, 1) { revert(0, 0) } sstore(INITIALIZED_SLOT, 1) } _; } /** * @notice Sets up deployer as a proxy governance */ constructor() { address _governanceAddress = msg.sender; assembly { sstore(GOVERNANCE_SLOT, _governanceAddress) } } /** * @notice Detect whether or not governance is killed * @return Return true if governance is killed, false if not * @dev If governance is killed this contract becomes immutable */ function governanceIsKilled() public view returns (bool) { return governanceAddress() == address(0); } /** * @notice Kill governance, making this contract immutable * @dev Only governance can kil governance */ function killGovernance() external onlyGovernance { updateGovernanceAddress(address(0)); } /** * @notice Update implementation address * @param _interfaceAddress Address of the new interface * @dev Only governance can update implementation */ function updateInterfaceAddress(address _interfaceAddress) external onlyGovernance { assembly { sstore(IMPLEMENTATION_SLOT, _interfaceAddress) } } /** * @notice Actually updates interface, kept for etherscan pattern recognition * @param _implementationAddress Address of the new implementation * @dev Only governance can update implementation */ function updateImplementationAddress(address _implementationAddress) external onlyGovernance { assembly { sstore(IMPLEMENTATION_SLOT, _implementationAddress) } } /** * @notice Update implementation address * @param _logicAddress Address of the new implementation * @dev Only governance can update implementation */ function updateLogicAddress(address _logicAddress) external onlyGovernance { assembly { sstore(LOGIC_SLOT, _logicAddress) } } /** * @notice Update governance address * @param _governanceAddress New governance address * @dev Only governance can update governance */ function updateGovernanceAddress(address _governanceAddress) public onlyGovernance { assembly { sstore(GOVERNANCE_SLOT, _governanceAddress) } } /** * @notice Fetch the current implementation address * @return _implementationAddress Returns the current implementation address */ function implementationAddress() public view returns (address _implementationAddress) { assembly { _implementationAddress := sload(IMPLEMENTATION_SLOT) } } /** * @notice Fetch the current implementation address * @return _interfaceAddress Returns the current implementation address */ function interfaceAddress() public view virtual returns (address _interfaceAddress) { assembly { _interfaceAddress := sload(IMPLEMENTATION_SLOT) } } /** * @notice Fetch the current implementation address * @return _logicAddress Returns the current implementation address */ function logicAddress() public view virtual returns (address _logicAddress) { assembly { _logicAddress := sload(LOGIC_SLOT) } } /** * @notice Fetch current governance address * @return _governanceAddress Returns current governance address */ function governanceAddress() public view virtual returns (address _governanceAddress) { assembly { _governanceAddress := sload(GOVERNANCE_SLOT) } } /** * @notice Fallback function that delegatecalls the subimplementation instead of what's in the IMPLEMENTATION_SLOT */ function _delegateCallSubimplmentation() internal virtual { assembly { let contractLogic := sload(LOGIC_SLOT) calldatacopy(0x0, 0x0, calldatasize()) let success := delegatecall( gas(), contractLogic, 0x0, calldatasize(), 0, 0 ) let returnDataSize := returndatasize() returndatacopy(0, 0, returnDataSize) switch success case 0 { revert(0, returnDataSize) } default { return(0, returnDataSize) } } } /** * @notice Delegatecall fallback proxy */ fallback() external payable virtual { _delegateCallSubimplmentation(); } receive() external payable virtual { _delegateCallSubimplmentation(); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "metadata": { "bytecodeHash": "none" } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"name":"childInterfaceAddress","outputs":[{"internalType":"address","name":"_childInterface","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"childSubImplementationAddress","outputs":[{"internalType":"address","name":"_childSubImplementation","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"},{"internalType":"address","name":"_bribe","type":"address"},{"internalType":"address","name":"_ve","type":"address"}],"name":"createGauge","outputs":[{"internalType":"address","name":"lastGauge","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"governanceAddress","outputs":[{"internalType":"address","name":"_governanceAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"interfaceSourceAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isBoostPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_state","type":"bool"}],"name":"setBoostPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_childInterfaceAddress","type":"address"}],"name":"updateChildInterfaceAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_childSubImplementationAddress","type":"address"}],"name":"updateChildSubImplementationAddress","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50610d27806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063713561ae11610066578063713561ae14610103578063795053d3146101275780638c1a02171461013c5780638f5ffb8814610163578063bf4b5d361461017657600080fd5b80630dba8acb146100985780631c48e0fa146100c8578063294b4b60146100db5780635ae35d14146100f0575b600080fd5b6000546100ab906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ab6100d63660046103ad565b61019d565b6100ee6100e93660046103f0565b610223565b005b6100ee6100fe366004610419565b61028a565b60005461011790600160a01b900460ff1681565b60405190151581526020016100bf565b600080516020610cfb833981519152546100ab565b7f23762bb6469fe7a7bd6609262f442817ed09ca1f07add24ef069610d59c90649546100ab565b6100ee610171366004610419565b6102ee565b7fa7461aa7cde97eb2572f8234e341359c6baae47e1feeb3c235edffe5f0fc089d546100ab565b60006101a7610352565b604051637c643b2f60e11b81526001600160a01b038681166004830152858116602483015284811660448301523360648301529192509082169063f8c8765e90608401600060405180830381600087803b15801561020457600080fd5b505af1158015610218573d6000803e3d6000fd5b505050509392505050565b600080516020610cfb833981519152546001600160a01b0316336001600160a01b03161461026c5760405162461bcd60e51b815260040161026390610434565b60405180910390fd5b60008054911515600160a01b0260ff60a01b19909216919091179055565b600080516020610cfb833981519152546001600160a01b0316336001600160a01b0316146102ca5760405162461bcd60e51b815260040161026390610434565b7f23762bb6469fe7a7bd6609262f442817ed09ca1f07add24ef069610d59c9064955565b600080516020610cfb833981519152546001600160a01b0316336001600160a01b03161461032e5760405162461bcd60e51b815260040161026390610434565b7fa7461aa7cde97eb2572f8234e341359c6baae47e1feeb3c235edffe5f0fc089d55565b60008060405161036190610384565b604051809103906000f08015801561037d573d6000803e3d6000fd5b5092915050565b61089d8061045e83390190565b80356001600160a01b03811681146103a857600080fd5b919050565b6000806000606084860312156103c257600080fd5b6103cb84610391565b92506103d960208501610391565b91506103e760408501610391565b90509250925092565b60006020828403121561040257600080fd5b8135801515811461041257600080fd5b9392505050565b60006020828403121561042b57600080fd5b61041282610391565b6020808252600f908201526e4f6e6c7920676f7665726e616e636560881b60408201526060019056fe608060405234801561001057600080fd5b50337fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610381905560408051638c1a021760e01b815290516000918391638c1a0217916004808201926020929091908290030181865afa158015610076573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061009a91906100e7565b7f547b500e425d72fd0723933cceefc203cef652b4736fd04250c3369b3e1a0a7292909255507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55610117565b6000602082840312156100f957600080fd5b81516001600160a01b038116811461011057600080fd5b9392505050565b610777806101266000396000f3fe6080604052600436106100e15760003560e01c8063a99f141f1161007f578063b90d893011610059578063b90d893014610258578063b97a231914610204578063cf6126ed14610278578063eb5ee83a14610278576100f0565b8063a99f141f146101ef578063aa8a675414610204578063b56fbb9714610238576100f0565b8063654ea5e7116100bb578063654ea5e71461016f578063795053d314610184578063966dae0e146101995780639c1fcc4c146101bb576100f0565b8063179781c4146100f85780633c2b053a14610122578063551ee5701461014f576100f0565b366100f0576100ee610298565b005b6100ee610298565b34801561010457600080fd5b5061010d610338565b60405190151581526020015b60405180910390f35b34801561012e57600080fd5b50610137610352565b6040516001600160a01b039091168152602001610119565b34801561015b57600080fd5b506100ee61016a3660046106e0565b6103d0565b34801561017b57600080fd5b506100ee610423565b34801561019057600080fd5b50610137610467565b3480156101a557600080fd5b5060008051602061074b83398151915254610137565b3480156101c757600080fd5b507f5942be825425c77e56e4bce97986794ab0f100954e40fc1390ae0e003710a3ab54610137565b3480156101fb57600080fd5b506100ee6104bc565b34801561021057600080fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54610137565b34801561024457600080fd5b506100ee6102533660046106e0565b6105d8565b34801561026457600080fd5b506100ee6102733660046106e0565b610634565b34801561028457600080fd5b506100ee6102933660046106e0565b610690565b60006102b060008051602061074b8339815191525490565b6001600160a01b031663bf4b5d366040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103119190610704565b90503660008037600080366000845af43d806000803e81801561033357816000f35b816000fd5b600080610343610467565b6001600160a01b031614905090565b600061036a60008051602061074b8339815191525490565b6001600160a01b031663bf4b5d366040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cb9190610704565b905090565b6103d8610467565b6001600160a01b0316336001600160a01b0316146104115760405162461bcd60e51b815260040161040890610721565b60405180910390fd5b60008051602061074b83398151915255565b61042b610467565b6001600160a01b0316336001600160a01b03161461045b5760405162461bcd60e51b815260040161040890610721565b6104656000610634565b565b600061047f60008051602061074b8339815191525490565b6001600160a01b031663795053d36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a7573d6000803e3d6000fd5b60006104d460008051602061074b8339815191525490565b6001600160a01b0316638c1a02176040518163ffffffff1660e01b8152600401602060405180830381865afa158015610511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105359190610704565b9050806001600160a01b03166105697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b031614156105b45760405162461bcd60e51b81526020600482015260116024820152704e6f7468696e6720746f2075706461746560781b6044820152606401610408565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b6105e0610467565b6001600160a01b0316336001600160a01b0316146106105760405162461bcd60e51b815260040161040890610721565b7f5942be825425c77e56e4bce97986794ab0f100954e40fc1390ae0e003710a3ab55565b61063c610467565b6001600160a01b0316336001600160a01b03161461066c5760405162461bcd60e51b815260040161040890610721565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b610698610467565b6001600160a01b0316336001600160a01b0316146105b45760405162461bcd60e51b815260040161040890610721565b6001600160a01b03811681146106dd57600080fd5b50565b6000602082840312156106f257600080fd5b81356106fd816106c8565b9392505050565b60006020828403121561071657600080fd5b81516106fd816106c8565b6020808252600f908201526e4f6e6c7920676f7665726e616e636560881b60408201526060019056fe547b500e425d72fd0723933cceefc203cef652b4736fd04250c3369b3e1a0a72a164736f6c634300080b000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a164736f6c634300080b000a
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063713561ae11610066578063713561ae14610103578063795053d3146101275780638c1a02171461013c5780638f5ffb8814610163578063bf4b5d361461017657600080fd5b80630dba8acb146100985780631c48e0fa146100c8578063294b4b60146100db5780635ae35d14146100f0575b600080fd5b6000546100ab906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6100ab6100d63660046103ad565b61019d565b6100ee6100e93660046103f0565b610223565b005b6100ee6100fe366004610419565b61028a565b60005461011790600160a01b900460ff1681565b60405190151581526020016100bf565b600080516020610cfb833981519152546100ab565b7f23762bb6469fe7a7bd6609262f442817ed09ca1f07add24ef069610d59c90649546100ab565b6100ee610171366004610419565b6102ee565b7fa7461aa7cde97eb2572f8234e341359c6baae47e1feeb3c235edffe5f0fc089d546100ab565b60006101a7610352565b604051637c643b2f60e11b81526001600160a01b038681166004830152858116602483015284811660448301523360648301529192509082169063f8c8765e90608401600060405180830381600087803b15801561020457600080fd5b505af1158015610218573d6000803e3d6000fd5b505050509392505050565b600080516020610cfb833981519152546001600160a01b0316336001600160a01b03161461026c5760405162461bcd60e51b815260040161026390610434565b60405180910390fd5b60008054911515600160a01b0260ff60a01b19909216919091179055565b600080516020610cfb833981519152546001600160a01b0316336001600160a01b0316146102ca5760405162461bcd60e51b815260040161026390610434565b7f23762bb6469fe7a7bd6609262f442817ed09ca1f07add24ef069610d59c9064955565b600080516020610cfb833981519152546001600160a01b0316336001600160a01b03161461032e5760405162461bcd60e51b815260040161026390610434565b7fa7461aa7cde97eb2572f8234e341359c6baae47e1feeb3c235edffe5f0fc089d55565b60008060405161036190610384565b604051809103906000f08015801561037d573d6000803e3d6000fd5b5092915050565b61089d8061045e83390190565b80356001600160a01b03811681146103a857600080fd5b919050565b6000806000606084860312156103c257600080fd5b6103cb84610391565b92506103d960208501610391565b91506103e760408501610391565b90509250925092565b60006020828403121561040257600080fd5b8135801515811461041257600080fd5b9392505050565b60006020828403121561042b57600080fd5b61041282610391565b6020808252600f908201526e4f6e6c7920676f7665726e616e636560881b60408201526060019056fe608060405234801561001057600080fd5b50337fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610381905560408051638c1a021760e01b815290516000918391638c1a0217916004808201926020929091908290030181865afa158015610076573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061009a91906100e7565b7f547b500e425d72fd0723933cceefc203cef652b4736fd04250c3369b3e1a0a7292909255507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55610117565b6000602082840312156100f957600080fd5b81516001600160a01b038116811461011057600080fd5b9392505050565b610777806101266000396000f3fe6080604052600436106100e15760003560e01c8063a99f141f1161007f578063b90d893011610059578063b90d893014610258578063b97a231914610204578063cf6126ed14610278578063eb5ee83a14610278576100f0565b8063a99f141f146101ef578063aa8a675414610204578063b56fbb9714610238576100f0565b8063654ea5e7116100bb578063654ea5e71461016f578063795053d314610184578063966dae0e146101995780639c1fcc4c146101bb576100f0565b8063179781c4146100f85780633c2b053a14610122578063551ee5701461014f576100f0565b366100f0576100ee610298565b005b6100ee610298565b34801561010457600080fd5b5061010d610338565b60405190151581526020015b60405180910390f35b34801561012e57600080fd5b50610137610352565b6040516001600160a01b039091168152602001610119565b34801561015b57600080fd5b506100ee61016a3660046106e0565b6103d0565b34801561017b57600080fd5b506100ee610423565b34801561019057600080fd5b50610137610467565b3480156101a557600080fd5b5060008051602061074b83398151915254610137565b3480156101c757600080fd5b507f5942be825425c77e56e4bce97986794ab0f100954e40fc1390ae0e003710a3ab54610137565b3480156101fb57600080fd5b506100ee6104bc565b34801561021057600080fd5b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc54610137565b34801561024457600080fd5b506100ee6102533660046106e0565b6105d8565b34801561026457600080fd5b506100ee6102733660046106e0565b610634565b34801561028457600080fd5b506100ee6102933660046106e0565b610690565b60006102b060008051602061074b8339815191525490565b6001600160a01b031663bf4b5d366040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102ed573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103119190610704565b90503660008037600080366000845af43d806000803e81801561033357816000f35b816000fd5b600080610343610467565b6001600160a01b031614905090565b600061036a60008051602061074b8339815191525490565b6001600160a01b031663bf4b5d366040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103cb9190610704565b905090565b6103d8610467565b6001600160a01b0316336001600160a01b0316146104115760405162461bcd60e51b815260040161040890610721565b60405180910390fd5b60008051602061074b83398151915255565b61042b610467565b6001600160a01b0316336001600160a01b03161461045b5760405162461bcd60e51b815260040161040890610721565b6104656000610634565b565b600061047f60008051602061074b8339815191525490565b6001600160a01b031663795053d36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103a7573d6000803e3d6000fd5b60006104d460008051602061074b8339815191525490565b6001600160a01b0316638c1a02176040518163ffffffff1660e01b8152600401602060405180830381865afa158015610511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105359190610704565b9050806001600160a01b03166105697f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b6001600160a01b031614156105b45760405162461bcd60e51b81526020600482015260116024820152704e6f7468696e6720746f2075706461746560781b6044820152606401610408565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b6105e0610467565b6001600160a01b0316336001600160a01b0316146106105760405162461bcd60e51b815260040161040890610721565b7f5942be825425c77e56e4bce97986794ab0f100954e40fc1390ae0e003710a3ab55565b61063c610467565b6001600160a01b0316336001600160a01b03161461066c5760405162461bcd60e51b815260040161040890610721565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b610698610467565b6001600160a01b0316336001600160a01b0316146105b45760405162461bcd60e51b815260040161040890610721565b6001600160a01b03811681146106dd57600080fd5b50565b6000602082840312156106f257600080fd5b81356106fd816106c8565b9392505050565b60006020828403121561071657600080fd5b81516106fd816106c8565b6020808252600f908201526e4f6e6c7920676f7665726e616e636560881b60408201526060019056fe547b500e425d72fd0723933cceefc203cef652b4736fd04250c3369b3e1a0a72a164736f6c634300080b000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103a164736f6c634300080b000a
Deployed Bytecode Sourcemap
29075:470:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;822:37:3;;;;;-1:-1:-1;;;;;822:37:3;;;;;;-1:-1:-1;;;;;178:32:7;;;160:51;;148:2;133:18;822:37:3;;;;;;;;29160:277:0;;;;;;:::i;:::-;;:::i;29443:100::-;;;;;;:::i;:::-;;:::i;:::-;;1460:214:3;;;;;;:::i;:::-;;:::i;29128:25:0:-;;;;;-1:-1:-1;;;29128:25:0;;;;;;;;;1373:14:7;;1366:22;1348:41;;1336:2;1321:18;29128:25:0;1208:187:7;1316:215:4;-1:-1:-1;;;;;;;;;;;1493:22:4;1316:215;;1922:204:3;2089:20;2083:27;1922:204;;1214:240;;;;;;:::i;:::-;;:::i;1680:236::-;1871:28;1865:35;1680:236;;29160:277:0;29273:17;29314:19;:17;:19::i;:::-;29343:61;;-1:-1:-1;;;29343:61:0;;-1:-1:-1;;;;;1687:15:7;;;29343:61:0;;;1669:34:7;1739:15;;;1719:18;;;1712:43;1791:15;;;1771:18;;;1764:43;29393:10:0;1823:18:7;;;1816:43;29302:31:0;;-1:-1:-1;29343:29:0;;;;;;1603:19:7;;29343:61:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29160:277;;;;;:::o;29443:100::-;-1:-1:-1;;;;;;;;;;;1493:22:4;-1:-1:-1;;;;;677:33:4;:10;-1:-1:-1;;;;;677:33:4;;669:61;;;;-1:-1:-1;;;669:61:4;;;;;;;:::i;:::-;;;;;;;;;29514:13:0::1;:22:::0;;;::::1;;-1:-1:-1::0;;;29514:22:0::1;-1:-1:-1::0;;;;29514:22:0;;::::1;::::0;;;::::1;::::0;;29443:100::o;1460:214:3:-;-1:-1:-1;;;;;;;;;;;1493:22:4;-1:-1:-1;;;;;677:33:4;:10;-1:-1:-1;;;;;677:33:4;;669:61;;;;-1:-1:-1;;;669:61:4;;;;;;;:::i;:::-;1613:20:3::1;1606:52:::0;1460:214::o;1214:240::-;-1:-1:-1;;;;;;;;;;;1493:22:4;-1:-1:-1;;;;;677:33:4;:10;-1:-1:-1;;;;;677:33:4;;669:61;;;;-1:-1:-1;;;669:61:4;;;;;;;:::i;:::-;1377:28:3::1;1370:68:::0;1214:240::o;866:142::-;913:7;932:12;955:23;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;932:47:3;866:142;-1:-1:-1;;866:142:3:o;-1:-1:-1:-;;;;;;;;:::o;222:173:7:-;290:20;;-1:-1:-1;;;;;339:31:7;;329:42;;319:70;;385:1;382;375:12;319:70;222:173;;;:::o;400:334::-;477:6;485;493;546:2;534:9;525:7;521:23;517:32;514:52;;;562:1;559;552:12;514:52;585:29;604:9;585:29;:::i;:::-;575:39;;633:38;667:2;656:9;652:18;633:38;:::i;:::-;623:48;;690:38;724:2;713:9;709:18;690:38;:::i;:::-;680:48;;400:334;;;;;:::o;739:273::-;795:6;848:2;836:9;827:7;823:23;819:32;816:52;;;864:1;861;854:12;816:52;903:9;890:23;956:5;949:13;942:21;935:5;932:32;922:60;;978:1;975;968:12;922:60;1001:5;739:273;-1:-1:-1;;;739:273:7:o;1017:186::-;1076:6;1129:2;1117:9;1108:7;1104:23;1100:32;1097:52;;;1145:1;1142;1135:12;1097:52;1168:29;1187:9;1168:29;:::i;1870:339::-;2072:2;2054:21;;;2111:2;2091:18;;;2084:30;-1:-1:-1;;;2145:2:7;2130:18;;2123:45;2200:2;2185:18;;1870:339::o
Swarm Source
none
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ 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.