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 7 from a total of 7 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Change Router Ow... | 14907083 | 774 days ago | IN | 0 ETH | 0.00114228 | ||||
Add Approved Tok... | 14907080 | 774 days ago | IN | 0 ETH | 0.00221764 | ||||
Add SS Contract | 14907074 | 774 days ago | IN | 0 ETH | 0.00280196 | ||||
Add Dispenser Co... | 14907072 | 774 days ago | IN | 0 ETH | 0.00280192 | ||||
Add Fixed Rate C... | 14907069 | 774 days ago | IN | 0 ETH | 0.00280028 | ||||
Add Factory | 14907067 | 774 days ago | IN | 0 ETH | 0.00191456 | ||||
0x60806040 | 14907022 | 774 days ago | IN | Create: FactoryRouter | 0 ETH | 0.17018924 |
Latest 2 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
15109853 | 739 days ago | Contract Creation | 0 ETH | |||
14923483 | 771 days ago | Contract Creation | 0 ETH |
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:
FactoryRouter
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 import "./balancer/BFactory.sol"; import "../interfaces/IFactory.sol"; import "../interfaces/IERC20.sol"; import "../interfaces/IFixedRateExchange.sol"; import "../interfaces/IPool.sol"; import "../interfaces/IDispenser.sol"; import "../utils/SafeERC20.sol"; import "@openzeppelin/contracts/utils/math/SafeMath.sol"; contract FactoryRouter is BFactory, IFactoryRouter { using SafeERC20 for IERC20; using SafeMath for uint256; address public routerOwner; address public factory; address public fixedRate; uint256 public minVestingPeriodInBlocks = 2426000; uint256 public swapOceanFee = 1e15; //0.1% uint256 public swapNonOceanFee = 2e15; // 0.2% uint256 public consumeFee = 3e16; // 0.03 DT uint256 public providerFee = 0; // 0% address[] public approvedTokens; address[] public ssContracts; address[] public fixedrates; address[] public dispensers; // mapping(address => bool) public approvedTokens; // mapping(address => bool) public ssContracts; // mapping(address => bool) public fixedPrice; // mapping(address => bool) public dispenser; event NewPool(address indexed poolAddress, bool isOcean); event VestingPeriodChanges(address indexed caller, uint256 minVestingPeriodInBlocks); event RouterChanged(address indexed caller, address indexed newRouter); event FactoryContractChanged( address indexed caller, address indexed contractAddress ); event TokenAdded(address indexed caller, address indexed token); event TokenRemoved(address indexed caller, address indexed token); event SSContractAdded( address indexed caller, address indexed contractAddress ); event SSContractRemoved( address indexed caller, address indexed contractAddress ); event FixedRateContractAdded( address indexed caller, address indexed contractAddress ); event FixedRateContractRemoved( address indexed caller, address indexed contractAddress ); event DispenserContractAdded( address indexed caller, address indexed contractAddress ); event DispenserContractRemoved( address indexed caller, address indexed contractAddress ); event OPCFeeChanged(address indexed caller, uint256 newSwapOceanFee, uint256 newSwapNonOceanFee, uint256 newConsumeFee, uint256 newProviderFee); modifier onlyRouterOwner() { require(routerOwner == msg.sender, "OceanRouter: NOT OWNER"); _; } event OPCCollectorChanged(address indexed caller, address indexed _newOpcCollector); constructor( address _routerOwner, address _oceanToken, address _bpoolTemplate, address _opcCollector, address[] memory _preCreatedPools ) BFactory(_bpoolTemplate, _opcCollector, _preCreatedPools) { require( _routerOwner != address(0), "FactoryRouter: Invalid router owner" ); require( _opcCollector != address(0), "FactoryRouter: Invalid opcCollector" ); require( _oceanToken != address(0), "FactoryRouter: Invalid Ocean Token address" ); routerOwner = _routerOwner; opcCollector = _opcCollector; _addApprovedToken(_oceanToken); } function changeRouterOwner(address _routerOwner) external onlyRouterOwner { require(_routerOwner != address(0), "Invalid new router owner"); routerOwner = _routerOwner; emit RouterChanged(msg.sender, _routerOwner); } /** * @dev addApprovedToken * Adds a token to the list of tokens with reduced fees * @param tokenAddress address Token to be added */ function addApprovedToken(address tokenAddress) external onlyRouterOwner { _addApprovedToken(tokenAddress); } function _addApprovedToken(address tokenAddress) internal { if(!isApprovedToken(tokenAddress)){ approvedTokens.push(tokenAddress); emit TokenAdded(msg.sender, tokenAddress); } } /** * @dev removeApprovedToken * Removes a token if exists from the list of tokens with reduced fees * @param tokenAddress address Token to be removed */ function removeApprovedToken(address tokenAddress) external onlyRouterOwner { require( tokenAddress != address(0), "FactoryRouter: Invalid Ocean Token address" ); uint256 i; for (i = 0; i < approvedTokens.length; i++) { if(approvedTokens[i] == tokenAddress) break; } if(i < approvedTokens.length){ approvedTokens[i] = approvedTokens[approvedTokens.length -1]; approvedTokens.pop(); emit TokenRemoved(msg.sender, tokenAddress); } } /** * @dev isApprovedToken * Returns true if token exists in the list of tokens with reduced fees * @param tokenAddress address Token to be checked */ function isApprovedToken(address tokenAddress) public view returns(bool) { for (uint256 i = 0; i < approvedTokens.length; i++) { if(approvedTokens[i] == tokenAddress) return true; } return false; } /** * @dev getApprovedTokens * Returns the list of tokens with reduced fees */ function getApprovedTokens() public view returns(address[] memory) { return(approvedTokens); } /** * @dev addSSContract * Adds a token to the list of ssContracts * @param _ssContract address Contract to be added */ function addSSContract(address _ssContract) external onlyRouterOwner { require( _ssContract != address(0), "FactoryRouter: Invalid _ssContract address" ); if(!isSSContract(_ssContract)){ ssContracts.push(_ssContract); emit SSContractAdded(msg.sender, _ssContract); } } /** * @dev removeSSContract * Removes a token if exists from the list of ssContracts * @param _ssContract address Contract to be removed */ function removeSSContract(address _ssContract) external onlyRouterOwner { require( _ssContract != address(0), "FactoryRouter: Invalid _ssContract address" ); uint256 i; for (i = 0; i < ssContracts.length; i++) { if(ssContracts[i] == _ssContract) break; } if(i < ssContracts.length){ // it's in the array ssContracts[i] = ssContracts[ssContracts.length -1]; ssContracts.pop(); emit SSContractRemoved(msg.sender, _ssContract); } } /** * @dev isSSContract * Returns true if token exists in the list of ssContracts * @param _ssContract address Contract to be checked */ function isSSContract(address _ssContract) public view returns(bool) { for (uint256 i = 0; i < ssContracts.length; i++) { if(ssContracts[i] == _ssContract) return true; } return false; } /** * @dev getSSContracts * Returns the list of ssContracts */ function getSSContracts() public view returns(address[] memory) { return(ssContracts); } function addFactory(address _factory) external onlyRouterOwner { require( _factory != address(0), "FactoryRouter: Invalid _factory address" ); require(factory == address(0), "FACTORY ALREADY SET"); factory = _factory; emit FactoryContractChanged(msg.sender, _factory); } /** * @dev addFixedRateContract * Adds an address to the list of fixed rate contracts * @param _fixedRate address Contract to be added */ function addFixedRateContract(address _fixedRate) external onlyRouterOwner { require( _fixedRate != address(0), "FactoryRouter: Invalid _fixedRate address" ); if(!isFixedRateContract(_fixedRate)){ fixedrates.push(_fixedRate); emit FixedRateContractAdded(msg.sender, _fixedRate); } } /** * @dev removeFixedRateContract * Removes an address from the list of fixed rate contracts * @param _fixedRate address Contract to be removed */ function removeFixedRateContract(address _fixedRate) external onlyRouterOwner { require( _fixedRate != address(0), "FactoryRouter: Invalid _fixedRate address" ); uint256 i; for (i = 0; i < fixedrates.length; i++) { if(fixedrates[i] == _fixedRate) break; } if(i < fixedrates.length){ // it's in the array fixedrates[i] = fixedrates[fixedrates.length -1]; fixedrates.pop(); emit FixedRateContractRemoved(msg.sender, _fixedRate); } } /** * @dev isFixedRateContract * Removes true if address exists in the list of fixed rate contracts * @param _fixedRate address Contract to be checked */ function isFixedRateContract(address _fixedRate) public view returns(bool) { for (uint256 i = 0; i < fixedrates.length; i++) { if(fixedrates[i] == _fixedRate) return true; } return false; } /** * @dev getFixedRatesContracts * Returns the list of fixed rate contracts */ function getFixedRatesContracts() public view returns(address[] memory) { return(fixedrates); } /** * @dev addDispenserContract * Adds an address to the list of dispensers * @param _dispenser address Contract to be added */ function addDispenserContract(address _dispenser) external onlyRouterOwner { require( _dispenser != address(0), "FactoryRouter: Invalid _dispenser address" ); if(!isDispenserContract(_dispenser)){ dispensers.push(_dispenser); emit DispenserContractAdded(msg.sender, _dispenser); } } /** * @dev removeDispenserContract * Removes an address from the list of dispensers * @param _dispenser address Contract to be removed */ function removeDispenserContract(address _dispenser) external onlyRouterOwner { require( _dispenser != address(0), "FactoryRouter: Invalid _dispenser address" ); uint256 i; for (i = 0; i < dispensers.length; i++) { if(dispensers[i] == _dispenser) break; } if(i < dispensers.length){ // it's in the array dispensers[i] = dispensers[dispensers.length -1]; dispensers.pop(); emit DispenserContractRemoved(msg.sender, _dispenser); } } /** * @dev isDispenserContract * Returns true if address exists in the list of dispensers * @param _dispenser address Contract to be checked */ function isDispenserContract(address _dispenser) public view returns(bool) { for (uint256 i = 0; i < dispensers.length; i++) { if(dispensers[i] == _dispenser) return true; } return false; } /** * @dev getDispensersContracts * Returns the list of fixed rate contracts */ function getDispensersContracts() public view returns(address[] memory) { return(dispensers); } /** * @dev getOPCFee * Gets OP Community Fees for a particular token * @param baseToken address token to be checked */ function getOPCFee(address baseToken) public view returns (uint256) { if (isApprovedToken(baseToken)) { return swapOceanFee; } else return swapNonOceanFee; } /** * @dev getOPCFees * Gets OP Community Fees for approved tokens and non approved tokens */ function getOPCFees() public view returns (uint256,uint256) { return (swapOceanFee, swapNonOceanFee); } /** * @dev getConsumeFee * Gets OP Community Fee cuts for consume fees */ function getOPCConsumeFee() public view returns (uint256) { return consumeFee; } /** * @dev getOPCProviderFee * Gets OP Community Fee cuts for provider fees */ function getOPCProviderFee() public view returns (uint256) { return providerFee; } /** * @dev updateOPCFee * Updates OP Community Fees * @param _newSwapOceanFee Amount charged for swapping with ocean approved tokens * @param _newSwapNonOceanFee Amount charged for swapping with non ocean approved tokens * @param _newConsumeFee Amount charged from consumeFees * @param _newProviderFee Amount charged for providerFees */ function updateOPCFee(uint256 _newSwapOceanFee, uint256 _newSwapNonOceanFee, uint256 _newConsumeFee, uint256 _newProviderFee) external onlyRouterOwner { swapOceanFee = _newSwapOceanFee; swapNonOceanFee = _newSwapNonOceanFee; consumeFee = _newConsumeFee; providerFee = _newProviderFee; emit OPCFeeChanged(msg.sender, _newSwapOceanFee, _newSwapNonOceanFee, _newConsumeFee, _newProviderFee); } /* * @dev getMinVestingPeriod * Returns current minVestingPeriodInBlocks @return minVestingPeriodInBlocks */ function getMinVestingPeriod() public view returns (uint256) { return minVestingPeriodInBlocks; } /* * @dev updateMinVestingPeriod * Set new minVestingPeriodInBlocks * @param _newPeriod */ function updateMinVestingPeriod(uint256 _newPeriod) external onlyRouterOwner { minVestingPeriodInBlocks = _newPeriod; emit VestingPeriodChanges(msg.sender, _newPeriod); } /** * @dev Deploys a new `OceanPool` on Ocean Friendly Fork modified for 1SS. This function cannot be called directly, but ONLY through the ERC20DT contract from a ERC20DEployer role ssContract address tokens [datatokenAddress, baseTokenAddress] publisherAddress user which will be assigned the vested amount. * @param tokens precreated parameter * @param ssParams params for the ssContract. * [0] = rate (wei) * [1] = baseToken decimals * [2] = vesting amount (wei) * [3] = vested blocks * [4] = initial liquidity in baseToken for pool creation * @param swapFees swapFees (swapFee, swapMarketFee), swapOceanFee will be set automatically later * [0] = swapFee for LP Providers * [1] = swapFee for marketplace runner . * @param addresses refers to an array of addresses passed by user * [0] = side staking contract address * [1] = baseToken address for pool creation(OCEAN or other) * [2] = baseTokenSender user which will provide the baseToken amount for initial liquidity * [3] = publisherAddress user which will be assigned the vested amount * [4] = marketFeeCollector marketFeeCollector address [5] = poolTemplateAddress @return pool address */ function deployPool( address[2] calldata tokens, // [datatokenAddress, baseTokenAddress] uint256[] calldata ssParams, uint256[] calldata swapFees, address[] calldata addresses ) external returns ( //[controller,baseTokenAddress,baseTokenSender,publisherAddress, marketFeeCollector,poolTemplateAddress] address ) { require( IFactory(factory).erc20List(msg.sender), "FACTORY ROUTER: NOT ORIGINAL ERC20 TEMPLATE" ); require(isSSContract(addresses[0]), "FACTORY ROUTER: invalid ssContract" ); require(ssParams[1] > 0, "Wrong decimals"); // we pull baseToken for creating initial pool and send it to the controller (ssContract) _pullUnderlying(tokens[1],addresses[2], addresses[0], ssParams[4]); address pool = newBPool(tokens, ssParams, swapFees, addresses); require(pool != address(0), "FAILED TO DEPLOY POOL"); if (isApprovedToken(tokens[1])) emit NewPool(pool, true); else emit NewPool(pool, false); return pool; } function _getLength(IERC20[] memory array) internal pure returns (uint256) { return array.length; } /** * @dev deployFixedRate * Creates a new FixedRateExchange setup. * As for deployPool, this function cannot be called directly, * but ONLY through the ERC20DT contract from a ERC20DEployer role * @param fixedPriceAddress fixedPriceAddress * @param addresses array of addresses [baseToken,owner,marketFeeCollector] * @param uints array of uints [baseTokenDecimals,datatokenDecimals, fixedRate, marketFee, withMint] @return exchangeId */ function deployFixedRate( address fixedPriceAddress, address[] calldata addresses, uint256[] calldata uints ) external returns (bytes32 exchangeId) { require( IFactory(factory).erc20List(msg.sender), "FACTORY ROUTER: NOT ORIGINAL ERC20 TEMPLATE" ); require(isFixedRateContract(fixedPriceAddress), "FACTORY ROUTER: Invalid FixedPriceContract" ); exchangeId = IFixedRateExchange(fixedPriceAddress).createWithDecimals( msg.sender, addresses, uints ); } /** * @dev deployDispenser * Activates a new Dispenser * As for deployPool, this function cannot be called directly, * but ONLY through the ERC20DT contract from a ERC20DEployer role * @param _dispenser dispenser contract address * @param datatoken refers to datatoken address. * @param maxTokens - max tokens to dispense * @param maxBalance - max balance of requester. * @param owner - owner * @param allowedSwapper - if !=0, only this address can request DTs */ function deployDispenser( address _dispenser, address datatoken, uint256 maxTokens, uint256 maxBalance, address owner, address allowedSwapper ) external { require( IFactory(factory).erc20List(msg.sender), "FACTORY ROUTER: NOT ORIGINAL ERC20 TEMPLATE" ); require(isDispenserContract(_dispenser), "FACTORY ROUTER: Invalid DispenserContract" ); IDispenser(_dispenser).create( datatoken, maxTokens, maxBalance, owner, allowedSwapper ); } /** * @dev addPoolTemplate * Adds an address to the list of pools templates * @param poolTemplate address Contract to be added */ function addPoolTemplate(address poolTemplate) external onlyRouterOwner { _addPoolTemplate(poolTemplate); } /** * @dev removePoolTemplate * Removes an address from the list of pool templates * @param poolTemplate address Contract to be removed */ function removePoolTemplate(address poolTemplate) external onlyRouterOwner { _removePoolTemplate(poolTemplate); } // If you need to buy multiple DT (let's say for a compute job which has multiple datasets), // you have to send one transaction for each DT that you want to buy. // Perks: // one single call to buy multiple DT for multiple assets (better UX, better gas optimization) // require tokenIn approvals for router from user. (except for dispenser operations) function buyDTBatch(Operations[] calldata _operations) external { // TODO: to avoid DOS attack, we set a limit to maximum orders (50?) require(_operations.length <= 50, "FactoryRouter: Too Many Operations"); for (uint256 i = 0; i < _operations.length; i++) { // address[] memory tokenInOutMarket = new address[](3); address[3] memory tokenInOutMarket = [ _operations[i].tokenIn, _operations[i].tokenOut, _operations[i].marketFeeAddress ]; uint256[4] memory amountsInOutMaxFee = [ _operations[i].amountsIn, _operations[i].amountsOut, _operations[i].maxPrice, _operations[i].swapMarketFee ]; // tokenInOutMarket[0] = if (_operations[i].operation == operationType.SwapExactIn) { // Get amountIn from user to router _pullUnderlying(_operations[i].tokenIn,msg.sender, address(this), _operations[i].amountsIn); // we approve pool to pull token from router IERC20(_operations[i].tokenIn).safeIncreaseAllowance( _operations[i].source, _operations[i].amountsIn ); // Perform swap (uint256 amountReceived, ) = IPool(_operations[i].source) .swapExactAmountIn(tokenInOutMarket, amountsInOutMaxFee); // transfer token swapped to user IERC20(_operations[i].tokenOut).safeTransfer( msg.sender, amountReceived ); } else if (_operations[i].operation == operationType.SwapExactOut) { // calculate how much amount In we need for exact Out uint256 amountIn; (amountIn, , , , ) = IPool(_operations[i].source) .getAmountInExactOut( _operations[i].tokenIn, _operations[i].tokenOut, _operations[i].amountsOut, _operations[i].swapMarketFee ); // pull amount In from user _pullUnderlying(_operations[i].tokenIn,msg.sender, address(this), amountIn); // we approve pool to pull token from router IERC20(_operations[i].tokenIn).safeIncreaseAllowance( _operations[i].source, amountIn ); // perform swap (uint tokenAmountIn,) = IPool(_operations[i].source).swapExactAmountOut( tokenInOutMarket, amountsInOutMaxFee ); require(tokenAmountIn <= amountsInOutMaxFee[0], 'TOO MANY TOKENS IN'); // send amount out back to user IERC20(_operations[i].tokenOut).safeTransfer( msg.sender, _operations[i].amountsOut ); } else if (_operations[i].operation == operationType.FixedRate) { // get datatoken address (, address datatoken, , , , , , , , , , ) = IFixedRateExchange( _operations[i].source ).getExchange(_operations[i].exchangeIds); // get tokenIn amount required for dt out (uint256 baseTokenAmount, , , ) = IFixedRateExchange( _operations[i].source ).calcBaseInGivenOutDT( _operations[i].exchangeIds, _operations[i].amountsOut, _operations[i].swapMarketFee ); // pull tokenIn amount _pullUnderlying(_operations[i].tokenIn,msg.sender, address(this), baseTokenAmount); // we approve pool to pull token from router IERC20(_operations[i].tokenIn).safeIncreaseAllowance( _operations[i].source, baseTokenAmount ); // perform swap IFixedRateExchange(_operations[i].source).buyDT( _operations[i].exchangeIds, _operations[i].amountsOut, _operations[i].amountsIn, _operations[i].marketFeeAddress, _operations[i].swapMarketFee ); // send dt out to user IERC20(datatoken).safeTransfer( msg.sender, _operations[i].amountsOut ); } else { IDispenser(_operations[i].source).dispense( _operations[i].tokenOut, _operations[i].amountsOut, msg.sender ); } } } // require pool[].baseToken (for each pool) approvals for router from user. function stakeBatch(Stakes[] calldata _stakes) external { // TODO: to avoid DOS attack, we set a limit to maximum orders (50?) require(_stakes.length <= 50, "FactoryRouter: Too Many Operations"); for (uint256 i = 0; i < _stakes.length; i++) { address baseToken = IPool(_stakes[i].poolAddress).getBaseTokenAddress(); _pullUnderlying(baseToken,msg.sender, address(this), _stakes[i].tokenAmountIn); uint256 balanceBefore = IERC20(_stakes[i].poolAddress).balanceOf(address(this)); // we approve pool to pull token from router IERC20(baseToken).safeIncreaseAllowance( _stakes[i].poolAddress, _stakes[i].tokenAmountIn); //now stake uint poolAmountOut = IPool(_stakes[i].poolAddress).joinswapExternAmountIn( _stakes[i].tokenAmountIn, _stakes[i].minPoolAmountOut ); require(poolAmountOut >= _stakes[i].minPoolAmountOut,'NOT ENOUGH LP'); uint256 balanceAfter = IERC20(_stakes[i].poolAddress).balanceOf(address(this)); //send LP shares to user IERC20(_stakes[i].poolAddress).safeTransfer( msg.sender, balanceAfter.sub(balanceBefore) ); } } function _pullUnderlying( address erc20, address from, address to, uint256 amount ) internal { uint256 balanceBefore = IERC20(erc20).balanceOf(to); IERC20(erc20).safeTransferFrom(from, to, amount); require(IERC20(erc20).balanceOf(to) >= balanceBefore.add(amount), "Transfer amount is too low"); } function getPoolTemplates() public view override(BFactory, IFactoryRouter) returns (address[] memory) { return BFactory.getPoolTemplates(); } function isPoolTemplate(address poolTemplate) public view override(BFactory, IFactoryRouter) returns (bool) { return BFactory.isPoolTemplate(poolTemplate); } /* * @dev updateOPCCollector * Set new opcCollector * @param opcCollector */ function updateOPCCollector(address _opcCollector) external onlyRouterOwner { require(_opcCollector != address(0), "New opcCollector cannot be ZERO_ADDR"); opcCollector = _opcCollector; emit OPCCollectorChanged(msg.sender, _opcCollector); } /* * @dev getOPCCollector * getter for opcCollector */ function getOPCCollector() view public returns (address) { return opcCollector; } }
pragma solidity 0.8.12; // Copyright Balancer, BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 import "./BPool.sol"; import "./BConst.sol"; import "../../utils/Deployer.sol"; import "../../interfaces/ISideStaking.sol"; import "../../interfaces/IERC20.sol"; /* * @title BFactory contract * @author Ocean Protocol (with code from Balancer Labs) * * @dev Ocean implementation of Balancer BPool Factory * BFactory deploys BPool proxy contracts. * New BPool proxy contracts are links to the template contract's bytecode. * Proxy contract functionality is based on Ocean Protocol custom * implementation of ERC1167 standard. */ contract BFactory is BConst, Deployer { address public opcCollector; // mapping(address => bool) internal poolTemplates; address[] public poolTemplates; event BPoolCreated( address indexed newBPoolAddress, address indexed registeredBy, address indexed datatokenAddress, address baseTokenAddress, address bpoolTemplateAddress, address ssAddress ); event PoolTemplateAdded( address indexed caller, address indexed contractAddress ); event PoolTemplateRemoved( address indexed caller, address indexed contractAddress ); /* @dev Called on contract deployment. Cannot be called with zero address. @param _bpoolTemplate -- address of a deployed BPool contract. @param _preCreatedPools list of pre-created pools. It can be only used in case of migration from an old factory contract. */ constructor( address _bpoolTemplate, address _opcCollector, address[] memory _preCreatedPools ) { require( _bpoolTemplate != address(0), "BFactory: invalid bpool template zero address" ); require(_opcCollector != address(0), "BFactory: zero address"); opcCollector = _opcCollector; _addPoolTemplate(_bpoolTemplate); if (_preCreatedPools.length > 0) { for (uint256 i = 0; i < _preCreatedPools.length; i++) { emit BPoolCreated( _preCreatedPools[i], msg.sender, address(0), address(0), address(0), address(0) ); } } } /** * @dev Deploys new BPool proxy contract. Template contract address could not be a zero address. * @param tokens [datatokenAddress, baseTokenAddress] * publisherAddress user which will be assigned the vested amount. * @param ssParams params for the ssContract. * @param swapFees swapFees (swapFee, swapMarketFee), swapOceanFee will be set automatically later marketFeeCollector marketFeeCollector address @param addresses // array of addresses passed by the user [controller,baseTokenAddress,baseTokenSender,publisherAddress, marketFeeCollector,poolTemplate address] @return bpool address of a new proxy BPool contract */ function newBPool( address[2] memory tokens, uint256[] memory ssParams, uint256[] memory swapFees, address[] memory addresses ) internal returns (address bpool) { require(isPoolTemplate(addresses[5]), "BFactory: Wrong Pool Template"); address[1] memory feeCollectors = [addresses[4]]; bpool = deploy(addresses[5]); require(bpool != address(0), "BFactory: invalid bpool zero address"); BPool bpoolInstance = BPool(bpool); require( bpoolInstance.initialize( addresses[0], // ss is the pool controller address(this), swapFees, false, false, tokens, feeCollectors ), "ERR_INITIALIZE_BPOOL" ); // emit BPoolCreated(bpool, msg.sender,datatokenAddress,baseTokenAddress,bpoolTemplate,controller); // requires approval first from baseTokenSender require( ISideStaking(addresses[0]).newDatatokenCreated( tokens[0], tokens[1], bpool, addresses[3], //publisherAddress ssParams ), "ERR_INITIALIZE_SIDESTAKING" ); return bpool; } /** * @dev _addPoolTemplate * Adds an address to the list of pools templates * @param poolTemplate address Contract to be added */ function _addPoolTemplate(address poolTemplate) internal { require( poolTemplate != address(0), "FactoryRouter: Invalid poolTemplate address" ); if (!isPoolTemplate(poolTemplate)) { poolTemplates.push(poolTemplate); emit PoolTemplateAdded(msg.sender, poolTemplate); } } /** * @dev _removeFixedRateContract * Removes an address from the list of pool templates * @param poolTemplate address Contract to be removed */ function _removePoolTemplate(address poolTemplate) internal { uint256 i; for (i = 0; i < poolTemplates.length; i++) { if (poolTemplates[i] == poolTemplate) break; } if (i < poolTemplates.length) { // it's in the array for (uint256 c = i; c < poolTemplates.length - 1; c++) { poolTemplates[c] = poolTemplates[c + 1]; } poolTemplates.pop(); emit PoolTemplateRemoved(msg.sender, poolTemplate); } } /** * @dev isPoolTemplate * Removes true if address exists in the list of templates * @param poolTemplate address Contract to be checked */ function isPoolTemplate(address poolTemplate) public view virtual returns (bool) { for (uint256 i = 0; i < poolTemplates.length; i++) { if (poolTemplates[i] == poolTemplate) return true; } return false; } /** * @dev getPoolTemplates * Returns the list of pool templates */ function getPoolTemplates() public view virtual returns (address[] memory) { return (poolTemplates); } }
pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 interface IFactory { function createToken( uint256 _templateIndex, string[] calldata strings, address[] calldata addresses, uint256[] calldata uints, bytes[] calldata bytess ) external returns (address token); function erc721List(address ERC721address) external returns (address); function erc20List(address erc20dt) external view returns(bool); struct NftCreateData{ string name; string symbol; uint256 templateIndex; string tokenURI; bool transferable; address owner; } struct ErcCreateData{ uint256 templateIndex; string[] strings; address[] addresses; uint256[] uints; bytes[] bytess; } struct PoolData{ uint256[] ssParams; uint256[] swapFees; address[] addresses; } struct FixedData{ address fixedPriceAddress; address[] addresses; uint256[] uints; } struct DispenserData{ address dispenserAddress; uint256 maxTokens; uint256 maxBalance; bool withMint; address allowedSwapper; } function createNftWithErc20( NftCreateData calldata _NftCreateData, ErcCreateData calldata _ErcCreateData ) external returns (address , address); function createNftWithErc20WithPool( NftCreateData calldata _NftCreateData, ErcCreateData calldata _ErcCreateData, PoolData calldata _PoolData ) external returns (address, address , address); function createNftWithErc20WithFixedRate( NftCreateData calldata _NftCreateData, ErcCreateData calldata _ErcCreateData, FixedData calldata _FixedData ) external returns (address, address , bytes32 ); function createNftWithErc20WithDispenser( NftCreateData calldata _NftCreateData, ErcCreateData calldata _ErcCreateData, DispenserData calldata _DispenserData ) external returns (address, address); }
pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { function decimals() external view returns (uint8); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @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); }
pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 interface IFixedRateExchange { function createWithDecimals( address datatoken, address[] calldata addresses, // [baseToken,owner,marketFeeCollector] uint256[] calldata uints // [baseTokenDecimals,datatokenDecimals, fixedRate, marketFee] ) external returns (bytes32 exchangeId); function buyDT(bytes32 exchangeId, uint256 datatokenAmount, uint256 maxBaseTokenAmount, address consumeMarketAddress, uint256 consumeMarketSwapFeeAmount) external; function sellDT(bytes32 exchangeId, uint256 datatokenAmount, uint256 minBaseTokenAmount, address consumeMarketAddress, uint256 consumeMarketSwapFeeAmount) external; function getAllowedSwapper(bytes32 exchangeId) external view returns (address allowedSwapper); function getExchange(bytes32 exchangeId) external view returns ( address exchangeOwner, address datatoken, uint256 dtDecimals, address baseToken, uint256 btDecimals, uint256 fixedRate, bool active, uint256 dtSupply, uint256 btSupply, uint256 dtBalance, uint256 btBalance, bool withMint //address allowedSwapper ); function getFeesInfo(bytes32 exchangeId) external view returns ( uint256 marketFee, address marketFeeCollector, uint256 opcFee, uint256 marketFeeAvailable, uint256 oceanFeeAvailable ); function isActive(bytes32 exchangeId) external view returns (bool); function calcBaseInGivenOutDT(bytes32 exchangeId, uint256 datatokenAmount, uint256 consumeMarketSwapFeeAmount) external view returns ( uint256 baseTokenAmount, uint256 oceanFeeAmount, uint256 publishMarketFeeAmount, uint256 consumeMarketFeeAmount ); function calcBaseOutGivenInDT(bytes32 exchangeId, uint256 datatokenAmount, uint256 consumeMarketSwapFeeAmount) external view returns ( uint256 baseTokenAmount, uint256 oceanFeeAmount, uint256 publishMarketFeeAmount, uint256 consumeMarketFeeAmount ); function updateMarketFee(bytes32 exchangeId, uint256 _newMarketFee) external; function updateMarketFeeCollector(bytes32 exchangeId, address _newMarketCollector) external; function setAllowedSwapper(bytes32 exchangeId, address newAllowedSwapper) external; function getId() pure external returns (uint8); function collectBT(bytes32 exchangeId, uint256 amount) external; function collectDT(bytes32 exchangeId, uint256 amount) external; }
// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.8.12; // Copyright Balancer, BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 interface IPool { function getDatatokenAddress() external view returns (address); function getBaseTokenAddress() external view returns (address); function getController() external view returns (address); function setup( address datatokenAddress, uint256 datatokenAmount, uint256 datatokennWeight, address baseTokenAddress, uint256 baseTokenAmount, uint256 baseTokenWeight ) external; function swapExactAmountIn( address[3] calldata tokenInOutMarket, //[tokenIn,tokenOut,marketFeeAddress] uint256[4] calldata amountsInOutMaxFee //[tokenAmountIn,minAmountOut,maxPrice,_swapMarketFee] ) external returns (uint256 tokenAmountOut, uint256 spotPriceAfter); function swapExactAmountOut( address[3] calldata tokenInOutMarket, // [tokenIn,tokenOut,marketFeeAddress] uint256[4] calldata amountsInOutMaxFee // [maxAmountIn,tokenAmountOut,maxPrice,_swapMarketFee] ) external returns (uint256 tokenAmountIn, uint256 spotPriceAfter); function getAmountInExactOut( address tokenIn, address tokenOut, uint256 tokenAmountOut, uint256 _consumeMarketSwapFee ) external view returns (uint256, uint256, uint256, uint256, uint256); function getAmountOutExactIn( address tokenIn, address tokenOut, uint256 tokenAmountIn, uint256 _consumeMarketSwapFee ) external view returns (uint256, uint256, uint256, uint256, uint256); function setSwapFee(uint256 swapFee) external; function getId() pure external returns (uint8); function exitswapPoolAmountIn( uint256 poolAmountIn, uint256 minAmountOut ) external returns (uint256 tokenAmountOut); function joinswapExternAmountIn( uint256 tokenAmountIn, uint256 minPoolAmountOut ) external returns (uint256 poolAmountOut); }
pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 interface IDispenser { function status(address datatoken) external view returns ( bool active, address owner, bool isMinter, uint256 maxTokens, uint256 maxBalance, uint256 balance, address allowedSwapper ); function create( address datatoken,uint256 maxTokens, uint256 maxBalance, address owner, address allowedSwapper) external; function activate(address datatoken,uint256 maxTokens, uint256 maxBalance) external; function deactivate(address datatoken) external; function dispense(address datatoken, uint256 amount, address destination) external payable; function ownerWithdraw(address datatoken) external; function setAllowedSwapper(address datatoken, address newAllowedSwapper) external; function getId() pure external returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.12; import "../interfaces/IERC20.sol"; import "./ERC721/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; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } /** * @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, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol) pragma solidity ^0.8.0; // CAUTION // This version of SafeMath should only be used with Solidity 0.8 or later, // because it relies on the compiler's built in overflow checks. /** * @dev Wrappers over Solidity's arithmetic operations. * * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler * now has built in overflow checking. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ 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 substraction of two unsigned integers, with an overflow flag. * * _Available since v3.4._ */ 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. * * _Available since v3.4._ */ 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. * * _Available since v3.4._ */ 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. * * _Available since v3.4._ */ 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 addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { return a + b; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return a - b; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { return a * b; } /** * @dev Returns the integer division of two unsigned integers, reverting on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. * * Requirements: * * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return a / b; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return a % b; } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {trySub}. * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b <= a, errorMessage); return a - b; } } /** * @dev Returns the integer division of two unsigned integers, reverting with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function div( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a / b; } } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * reverting with custom message when dividing by zero. * * CAUTION: This function is deprecated because it requires allocating memory for the error * message unnecessarily. For custom revert reasons use {tryMod}. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * * - The divisor cannot be zero. */ function mod( uint256 a, uint256 b, string memory errorMessage ) internal pure returns (uint256) { unchecked { require(b > 0, errorMessage); return a % b; } } }
pragma solidity 0.8.12; // Copyright Balancer, BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 import "./BToken.sol"; import "./BMath.sol"; import "../../interfaces/IPool.sol"; import "../../interfaces/ISideStaking.sol"; import "../../utils/SafeERC20.sol"; /** * @title BPool * * @dev Used by the (Ocean version) BFactory contract as a bytecode reference to * deploy new BPools. * * This contract is a friendly fork of Balancer [1] * [1] https://github.com/balancer-labs/balancer-core/contracts/. * All fees are expressed in wei. Examples: * (1e17 = 10 % , 1e16 = 1% , 1e15 = 0.1%, 1e14 = 0.01%) */ contract BPool is BMath, BToken, IPool { using SafeERC20 for IERC20; struct Record { bool bound; // is token bound to pool uint256 index; // private uint256 denorm; // denormalized weight uint256 balance; } event LOG_SWAP( address indexed caller, address indexed tokenIn, address indexed tokenOut, uint256 tokenAmountIn, uint256 tokenAmountOut, uint256 timestamp, uint256 inBalance, uint256 outBalance, uint256 newSpotPrice ); event LOG_JOIN( address indexed caller, address indexed tokenIn, uint256 tokenAmountIn, uint256 timestamp ); event LOG_SETUP( address indexed caller, address indexed baseToken, uint256 baseTokenAmountIn, uint256 baseTokenWeight, address indexed datatoken, uint256 datatokenAmountIn, uint256 datatokenWeight ); event LOG_EXIT( address indexed caller, address indexed tokenOut, uint256 tokenAmountOut, uint256 timestamp ); event LOG_CALL( bytes4 indexed sig, address indexed caller, uint256 timestamp, bytes data ); event LOG_BPT(uint256 bptAmount); event LOG_BPT_SS(uint256 bptAmount); //emitted for SS contract event OPCFee( address caller, address OPCWallet, address token, uint256 amount ); event SwapFeeChanged(address caller, uint256 amount); event PublishMarketFee( address caller, address marketAddress, address token, uint256 amount ); // emited for fees sent to consumeMarket event ConsumeMarketFee(address to, address token, uint256 amount); event SWAP_FEES(uint LPFeeAmount, uint oceanFeeAmount, uint marketFeeAmount, uint consumeMarketFeeAmount, address tokenFeeAddress); //emitted for every change done by publisherMarket event PublishMarketFeeChanged(address caller, address newMarketCollector, uint256 swapFee); event Gulped(address token, uint256 oldBalance, uint256 newBalance); modifier _lock_() { require(!_mutex, "ERR_REENTRY"); _mutex = true; _; _mutex = false; } modifier _viewlock_() { require(!_mutex, "ERR_REENTRY"); _; } bool private _mutex; address private _controller; // has CONTROL role bool private _publicSwap; // true if PUBLIC can call SWAP functions //address public _publishMarketCollector; address public _publishMarketCollector; // `setSwapFee` and `finalize` require CONTROL // `finalize` sets `PUBLIC can SWAP`, `PUBLIC can JOIN` bool private _finalized; address[] private _tokens; mapping(address => Record) private _records; uint256 private _totalWeight; ISideStaking ssContract; //----------------------------------------------------------------------- //Proxy contract functionality: begin bool private initialized; /** * @dev getId * Return template id in case we need different ABIs. * If you construct your own template, please make sure to change the hardcoded value */ function getId() pure public returns (uint8) { return 1; } function isInitialized() external view returns (bool) { return initialized; } // Called prior to contract initialization (e.g creating new BPool instance) // Calls private _initialize function. Only if contract is not initialized. function initialize( address controller, address factory, uint256[] calldata swapFees, bool publicSwap, bool finalized, address[2] calldata tokens, address[1] calldata feeCollectors ) external returns (bool) { require(!initialized, "ERR_ALREADY_INITIALIZED"); require(controller != address(0), "ERR_INVALID_CONTROLLER_ADDRESS"); require(factory != address(0), "ERR_INVALID_FACTORY_ADDRESS"); require(swapFees[0] >= MIN_FEE, "ERR_MIN_FEE"); require(swapFees[0] <= MAX_FEE, "ERR_MAX_FEE"); require(swapFees[1] == 0 || swapFees[1]>= MIN_FEE, "ERR_MIN_FEE"); require(swapFees[1] <= MAX_FEE, "ERR_MAX_FEE"); return _initialize( controller, factory, swapFees, publicSwap, finalized, tokens, feeCollectors ); } // Private function called on contract initialization. function _initialize( address controller, address factory, uint256[] memory swapFees, bool publicSwap, bool finalized, address[2] memory tokens, address[1] memory feeCollectors ) private returns (bool) { _controller = controller; router = factory; _swapFee = swapFees[0]; emit SwapFeeChanged(msg.sender, _swapFee); _swapPublishMarketFee = swapFees[1]; _publicSwap = publicSwap; _finalized = finalized; _datatokenAddress = tokens[0]; _baseTokenAddress = tokens[1]; _publishMarketCollector = feeCollectors[0]; emit PublishMarketFeeChanged(msg.sender, _publishMarketCollector, _swapPublishMarketFee); initialized = true; ssContract = ISideStaking(_controller); return initialized; } /** * @dev setup * Initial setup of the pool * Can be called only by the controller * @param datatokenAddress datatokenAddress * @param datatokenAmount how many datatokens in the initial reserve * @param datatokenWeight datatoken weight (hardcoded in deployer at 50%) * @param baseTokenAddress base token * @param baseTokenAmount how many basetokens in the initial reserve * @param baseTokenWeight base weight (hardcoded in deployer at 50%) */ function setup( address datatokenAddress, uint256 datatokenAmount, uint256 datatokenWeight, address baseTokenAddress, uint256 baseTokenAmount, uint256 baseTokenWeight ) external _lock_ { require(msg.sender == _controller, "ERR_INVALID_CONTROLLER"); require( datatokenAddress == _datatokenAddress, "ERR_INVALID_DATATOKEN_ADDRESS" ); require( baseTokenAddress == _baseTokenAddress, "ERR_INVALID_baseToken_ADDRESS" ); // other inputs will be validated prior // calling the below functions // bind datatoken bind(datatokenAddress, datatokenAmount, datatokenWeight); emit LOG_JOIN( msg.sender, datatokenAddress, datatokenAmount, block.timestamp ); // bind baseToken bind(baseTokenAddress, baseTokenAmount, baseTokenWeight); emit LOG_JOIN( msg.sender, baseTokenAddress, baseTokenAmount, block.timestamp ); // finalize finalize(); emit LOG_SETUP( msg.sender, baseTokenAddress, baseTokenAmount, baseTokenWeight, datatokenAddress, datatokenAmount, datatokenWeight ); } //Proxy contract functionality: end //----------------------------------------------------------------------- /** * @dev isPublicSwap * Returns true if swapping is allowed */ function isPublicSwap() external view returns (bool) { return _publicSwap; } /** * @dev isFinalized * Returns true if pool is finalized */ function isFinalized() external view returns (bool) { return _finalized; } /** * @dev isBound * Returns true if token is bound * @param t token to be checked */ function isBound(address t) external view returns (bool) { return _records[t].bound; } function _checkBound(address token) internal view { require(_records[token].bound, "ERR_NOT_BOUND"); } /** * @dev getNumTokens * Returns number of tokens bounded to pool */ function getNumTokens() external view returns (uint256) { return _tokens.length; } /** * @dev getCurrentTokens * Returns tokens bounded to pool, before the pool is finalized */ function getCurrentTokens() external view _viewlock_ returns (address[] memory tokens) { return _tokens; } /** * @dev getFinalTokens * Returns tokens bounded to pool, after the pool was finalized */ function getFinalTokens() public view _viewlock_ returns (address[] memory tokens) { require(_finalized, "ERR_NOT_FINALIZED"); return _tokens; } /** * @dev collectOPC * Collects and send all OPC Fees to _opcCollector. * This funtion can be called by anyone, because fees are being sent to _opcCollector */ function collectOPC() external { address[] memory tokens = getFinalTokens(); for (uint256 i = 0; i < tokens.length; i++) { uint256 amount = communityFees[tokens[i]]; communityFees[tokens[i]] = 0; address _opcCollector = IFactoryRouter(router).getOPCCollector(); emit OPCFee(msg.sender, _opcCollector, tokens[i], amount); IERC20(tokens[i]).safeTransfer(_opcCollector, amount); } } /** * @dev getCurrentOPCFees * Get the current amount of fees which can be withdrawned by OPC * @return address[] - array of tokens addresses * uint256[] - array of amounts */ function getCurrentOPCFees() public view returns (address[] memory, uint256[] memory) { address[] memory poolTokens = getFinalTokens(); address[] memory tokens = new address[](poolTokens.length); uint256[] memory amounts = new uint256[](poolTokens.length); for (uint256 i = 0; i < poolTokens.length; i++) { tokens[i] = poolTokens[i]; amounts[i] = communityFees[poolTokens[i]]; } return (tokens, amounts); } /** * @dev getCurrentMarketFees * Get the current amount of fees which can be withdrawned by _publishMarketCollector * @return address[] - array of tokens addresses * uint256[] - array of amounts */ function getCurrentMarketFees() public view returns (address[] memory, uint256[] memory) { address[] memory poolTokens = getFinalTokens(); address[] memory tokens = new address[](poolTokens.length); uint256[] memory amounts = new uint256[](poolTokens.length); for (uint256 i = 0; i < poolTokens.length; i++) { tokens[i] = poolTokens[i]; amounts[i] = publishMarketFees[poolTokens[i]]; } return (tokens, amounts); } /** * @dev collectMarketFee * Collects and send all Market Fees to _publishMarketCollector. * This function can be called by anyone, because fees are being sent to _publishMarketCollector */ function collectMarketFee() external { address[] memory tokens = getFinalTokens(); for (uint256 i = 0; i < tokens.length; i++) { uint256 amount = publishMarketFees[tokens[i]]; publishMarketFees[tokens[i]] = 0; emit PublishMarketFee( msg.sender, _publishMarketCollector, tokens[i], amount ); IERC20(tokens[i]).safeTransfer(_publishMarketCollector, amount); } } /** * @dev updatePublishMarketFee * Set _newCollector as _publishMarketCollector * @param _newCollector new _publishMarketCollector * @param _newSwapFee new swapFee */ function updatePublishMarketFee(address _newCollector, uint256 _newSwapFee) external { require(_publishMarketCollector == msg.sender, "ONLY MARKET COLLECTOR"); require(_newCollector != address(0), "Invalid _newCollector address"); require(_newSwapFee ==0 || _newSwapFee >= MIN_FEE, "ERR_MIN_FEE"); require(_newSwapFee <= MAX_FEE, "ERR_MAX_FEE"); _publishMarketCollector = _newCollector; _swapPublishMarketFee = _newSwapFee; emit PublishMarketFeeChanged(msg.sender, _publishMarketCollector, _swapPublishMarketFee); } /** * @dev getDenormalizedWeight * Returns denormalized weight of a token * @param token token to be checked */ function getDenormalizedWeight(address token) external view _viewlock_ returns (uint256) { _checkBound(token); return _records[token].denorm; } /** * @dev getTotalDenormalizedWeight * Returns total denormalized weught of the pool */ function getTotalDenormalizedWeight() external view _viewlock_ returns (uint256) { return _totalWeight; } /** * @dev getNormalizedWeight * Returns normalized weight of a token * @param token token to be checked */ function getNormalizedWeight(address token) external view _viewlock_ returns (uint256) { _checkBound(token); uint256 denorm = _records[token].denorm; return bdiv(denorm, _totalWeight); } /** * @dev getBalance * Returns the current token reserve amount * @param token token to be checked */ function getBalance(address token) external view _viewlock_ returns (uint256) { _checkBound(token); return _records[token].balance; } /** * @dev getSwapFee * Returns the current Liquidity Providers swap fee */ function getSwapFee() external view returns (uint256) { return _swapFee; } /** * @dev getMarketFee * Returns the current fee of publishingMarket */ function getMarketFee() external view returns (uint256) { return _swapPublishMarketFee; } /** * @dev getController * Returns the current controller address (ssBot) */ function getController() external view returns (address) { return _controller; } /** * @dev getDatatokenAddress * Returns the current datatoken address */ function getDatatokenAddress() external view returns (address) { return _datatokenAddress; } /** * @dev getBaseTokenAddress * Returns the current baseToken address */ function getBaseTokenAddress() external view returns (address) { return _baseTokenAddress; } /** * @dev setSwapFee * Allows controller to change the swapFee * @param swapFee new swap fee (max 1e17 = 10 % , 1e16 = 1% , 1e15 = 0.1%, 1e14 = 0.01%) */ function setSwapFee(uint256 swapFee) public { require(msg.sender == _controller, "ERR_NOT_CONTROLLER"); require(swapFee >= MIN_FEE, "ERR_MIN_FEE"); require(swapFee <= MAX_FEE, "ERR_MAX_FEE"); _swapFee = swapFee; emit SwapFeeChanged(msg.sender, swapFee); } /** * @dev finalize * Finalize pool. After this,new tokens cannot be bound */ function finalize() internal { _finalized = true; _publicSwap = true; _mintPoolShare(INIT_POOL_SUPPLY); _pushPoolShare(msg.sender, INIT_POOL_SUPPLY); } /** * @dev bind * Bind a new token to the pool. * @param token token address * @param balance initial reserve * @param denorm denormalized weight */ function bind( address token, uint256 balance, uint256 denorm ) internal { require(msg.sender == _controller, "ERR_NOT_CONTROLLER"); require(!_records[token].bound, "ERR_IS_BOUND"); require(!_finalized, "ERR_IS_FINALIZED"); require(_tokens.length < MAX_BOUND_TOKENS, "ERR_MAX_TOKENS"); _records[token] = Record({ bound: true, index: _tokens.length, denorm: 0, // balance and denorm will be validated balance: 0 // and set by `rebind` }); _tokens.push(token); rebind(token, balance, denorm); } /** * @dev rebind * Update pool reserves & weight after a token bind * @param token token address * @param balance initial reserve * @param denorm denormalized weight */ function rebind( address token, uint256 balance, uint256 denorm ) internal { require(denorm >= MIN_WEIGHT, "ERR_MIN_WEIGHT"); require(denorm <= MAX_WEIGHT, "ERR_MAX_WEIGHT"); require(balance >= MIN_BALANCE, "ERR_MIN_BALANCE"); // Adjust the denorm and totalWeight uint256 oldWeight = _records[token].denorm; if (denorm > oldWeight) { _totalWeight = badd(_totalWeight, bsub(denorm, oldWeight)); require(_totalWeight <= MAX_TOTAL_WEIGHT, "ERR_MAX_TOTAL_WEIGHT"); } else if (denorm < oldWeight) { _totalWeight = bsub(_totalWeight, bsub(oldWeight, denorm)); } _records[token].denorm = denorm; // Adjust the balance record and actual token balance uint256 oldBalance = _records[token].balance; _records[token].balance = balance; if (balance > oldBalance) { _pullUnderlying(token, msg.sender, bsub(balance, oldBalance)); } else if (balance < oldBalance) { // In this case liquidity is being withdrawn, we don't have EXIT_FEES uint256 tokenBalanceWithdrawn = bsub(oldBalance, balance); _pushUnderlying( token, msg.sender, tokenBalanceWithdrawn ); } } /** * @dev getSpotPrice * Return the spot price of swapping tokenIn to tokenOut * @param tokenIn in token * @param tokenOut out token * @param _consumeMarketSwapFee consume market swap fee */ function getSpotPrice( address tokenIn, address tokenOut, uint256 _consumeMarketSwapFee ) external view _viewlock_ returns (uint256 spotPrice) { _checkBound(tokenIn); _checkBound(tokenOut); Record storage inRecord = _records[tokenIn]; Record storage outRecord = _records[tokenOut]; return calcSpotPrice( inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, _consumeMarketSwapFee ); } // view function used for batch buy. useful for frontend /** * @dev getAmountInExactOut * How many tokensIn do you need in order to get exact tokenAmountOut. Returns: tokenAmountIn, LPFee, opcFee , publishMarketSwapFee, consumeMarketSwapFee * @param tokenIn token to be swaped * @param tokenOut token to get * @param tokenAmountOut exact amount of tokenOut * @param _consumeMarketSwapFee consume market swap fee */ function getAmountInExactOut( address tokenIn, address tokenOut, uint256 tokenAmountOut, uint256 _consumeMarketSwapFee ) external view returns ( // _viewlock_ uint256 tokenAmountIn, uint lpFeeAmount, uint oceanFeeAmount, uint publishMarketSwapFeeAmount, uint consumeMarketSwapFeeAmount ) { _checkBound(tokenIn); _checkBound(tokenOut); uint256[4] memory data = [ _records[tokenIn].balance, _records[tokenIn].denorm, _records[tokenOut].balance, _records[tokenOut].denorm ]; uint tokenAmountInBalance; swapfees memory _swapfees; (tokenAmountIn, tokenAmountInBalance, _swapfees) = calcInGivenOut( data, tokenAmountOut, // tokenIn, _consumeMarketSwapFee ); return(tokenAmountIn, _swapfees.LPFee, _swapfees.oceanFeeAmount, _swapfees.publishMarketFeeAmount, _swapfees.consumeMarketFee); } // view function useful for frontend /** * @dev getAmountOutExactIn * How many tokensOut you will get for a exact tokenAmountIn Returns: tokenAmountOut, LPFee, opcFee , publishMarketSwapFee, consumeMarketSwapFee * @param tokenIn token to be swaped * @param tokenOut token to get * @param tokenAmountOut exact amount of tokenOut * @param _consumeMarketSwapFee consume market swap fee */ function getAmountOutExactIn( address tokenIn, address tokenOut, uint256 tokenAmountIn, uint256 _consumeMarketSwapFee ) external view returns ( // _viewlock_ uint256 tokenAmountOut, uint lpFeeAmount, uint oceanFeeAmount, uint publishMarketSwapFeeAmount, uint consumeMarketSwapFeeAmount ) { _checkBound(tokenIn); _checkBound(tokenOut); uint256[4] memory data = [ _records[tokenIn].balance, _records[tokenIn].denorm, _records[tokenOut].balance, _records[tokenOut].denorm ]; uint balanceInToAdd; swapfees memory _swapfees; (tokenAmountOut, balanceInToAdd, _swapfees) = calcOutGivenIn( data, tokenAmountIn, // tokenIn, _consumeMarketSwapFee ); return(tokenAmountOut, _swapfees.LPFee, _swapfees.oceanFeeAmount, _swapfees.publishMarketFeeAmount, _swapfees.consumeMarketFee); } /** * @dev swapExactAmountIn * Swaps an exact amount of tokensIn to get a mimum amount of tokenOut * @param tokenInOutMarket array of addreses: [tokenIn, tokenOut, consumeMarketFeeAddress] * @param amountsInOutMaxFee array of ints: [tokenAmountIn, minAmountOut, maxPrice, consumeMarketSwapFee] */ function swapExactAmountIn( address[3] calldata tokenInOutMarket, uint256[4] calldata amountsInOutMaxFee ) external _lock_ returns (uint256 tokenAmountOut, uint256 spotPriceAfter) { require(_finalized, "ERR_NOT_FINALIZED"); require(tokenInOutMarket[0] != tokenInOutMarket[1], 'Cannot swap same token'); _checkBound(tokenInOutMarket[0]); _checkBound(tokenInOutMarket[1]); Record storage inRecord = _records[address(tokenInOutMarket[0])]; Record storage outRecord = _records[address(tokenInOutMarket[1])]; require(amountsInOutMaxFee[3] ==0 || amountsInOutMaxFee[3] >= MIN_FEE,'ConsumeSwapFee too low'); require(amountsInOutMaxFee[3] <= MAX_FEE,'ConsumeSwapFee too high'); require( amountsInOutMaxFee[0] <= bmul(inRecord.balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO" ); uint256 spotPriceBefore = calcSpotPrice( inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, amountsInOutMaxFee[3] ); require( spotPriceBefore <= amountsInOutMaxFee[2], "ERR_BAD_LIMIT_PRICE" ); uint256 balanceInToAdd; uint256[4] memory data = [ inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm ]; swapfees memory _swapfees; (tokenAmountOut, balanceInToAdd, _swapfees) = calcOutGivenIn( data, amountsInOutMaxFee[0], // tokenInOutMarket[0], amountsInOutMaxFee[3] ); // update balances communityFees[tokenInOutMarket[0]] = badd(communityFees[tokenInOutMarket[0]],_swapfees.oceanFeeAmount); publishMarketFees[tokenInOutMarket[0]] = badd(publishMarketFees[tokenInOutMarket[0]],_swapfees.publishMarketFeeAmount); emit SWAP_FEES(_swapfees.LPFee, _swapfees.oceanFeeAmount, _swapfees.publishMarketFeeAmount,_swapfees.consumeMarketFee, tokenInOutMarket[0]); require(tokenAmountOut >= amountsInOutMaxFee[1], "ERR_LIMIT_OUT"); inRecord.balance = badd(inRecord.balance, balanceInToAdd); outRecord.balance = bsub(outRecord.balance, tokenAmountOut); spotPriceAfter = calcSpotPrice( inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, amountsInOutMaxFee[3] ); require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX"); require(spotPriceAfter <= amountsInOutMaxFee[2], "ERR_LIMIT_PRICE"); require( spotPriceBefore <= bdiv(amountsInOutMaxFee[0], tokenAmountOut), "ERR_MATH_APPROX" ); emit LOG_SWAP( msg.sender, tokenInOutMarket[0], tokenInOutMarket[1], amountsInOutMaxFee[0], tokenAmountOut, block.timestamp, inRecord.balance, outRecord.balance, spotPriceAfter ); _pullUnderlying(tokenInOutMarket[0], msg.sender, amountsInOutMaxFee[0]); uint256 consumeMarketFeeAmount = bsub( amountsInOutMaxFee[0], bmul(amountsInOutMaxFee[0], bsub(BONE, amountsInOutMaxFee[3])) ); if (amountsInOutMaxFee[3] > 0) { IERC20(tokenInOutMarket[0]).safeTransfer( tokenInOutMarket[2], consumeMarketFeeAmount ); emit ConsumeMarketFee( tokenInOutMarket[2], tokenInOutMarket[0], consumeMarketFeeAmount ); } _pushUnderlying(tokenInOutMarket[1], msg.sender, tokenAmountOut); return (tokenAmountOut, spotPriceAfter); //returning spot price 0 because there is no public spotPrice } /** * @dev swapExactAmountOut * Swaps a maximum maxAmountIn of tokensIn to get an exact amount of tokenOut * @param tokenInOutMarket array of addreses: [tokenIn, tokenOut, consumeMarketFeeAddress] * @param amountsInOutMaxFee array of ints: [maxAmountIn,tokenAmountOut,maxPrice, consumeMarketSwapFee] */ function swapExactAmountOut( address[3] calldata tokenInOutMarket, uint256[4] calldata amountsInOutMaxFee ) external _lock_ returns (uint256 tokenAmountIn, uint256 spotPriceAfter) { require(_finalized, "ERR_NOT_FINALIZED"); require(tokenInOutMarket[0] != tokenInOutMarket[1], 'Cannot swap same token'); require(amountsInOutMaxFee[3] ==0 || amountsInOutMaxFee[3] >= MIN_FEE,'ConsumeSwapFee too low'); require(amountsInOutMaxFee[3] <= MAX_FEE,'ConsumeSwapFee too high'); _checkBound(tokenInOutMarket[0]); _checkBound(tokenInOutMarket[1]); Record storage inRecord = _records[address(tokenInOutMarket[0])]; Record storage outRecord = _records[address(tokenInOutMarket[1])]; require( amountsInOutMaxFee[1] <= bmul(outRecord.balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO" ); uint256 spotPriceBefore = calcSpotPrice( inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, amountsInOutMaxFee[3] ); require( spotPriceBefore <= amountsInOutMaxFee[2], "ERR_BAD_LIMIT_PRICE" ); // this is the amount we are going to register in balances // (only takes account of swapFee, not OPC and market fee, //in order to not affect price during following swaps, fee wtihdrawl etc) uint256 balanceToAdd; uint256[4] memory data = [ inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm ]; swapfees memory _swapfees; (tokenAmountIn, balanceToAdd, _swapfees) = calcInGivenOut( data, amountsInOutMaxFee[1], //tokenInOutMarket[0], amountsInOutMaxFee[3] ); communityFees[tokenInOutMarket[0]] = badd(communityFees[tokenInOutMarket[0]],_swapfees.oceanFeeAmount); publishMarketFees[tokenInOutMarket[0]] = badd(publishMarketFees[tokenInOutMarket[0]],_swapfees.publishMarketFeeAmount); emit SWAP_FEES(_swapfees.LPFee, _swapfees.oceanFeeAmount, _swapfees.publishMarketFeeAmount,_swapfees.consumeMarketFee, tokenInOutMarket[0]); require(tokenAmountIn <= amountsInOutMaxFee[0], "ERR_LIMIT_IN"); inRecord.balance = badd(inRecord.balance, balanceToAdd); outRecord.balance = bsub(outRecord.balance, amountsInOutMaxFee[1]); spotPriceAfter = calcSpotPrice( inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, amountsInOutMaxFee[3] ); require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX"); require(spotPriceAfter <= amountsInOutMaxFee[2], "ERR_LIMIT_PRICE"); require( spotPriceBefore <= bdiv(tokenAmountIn, amountsInOutMaxFee[1]), "ERR_MATH_APPROX" ); emit LOG_SWAP( msg.sender, tokenInOutMarket[0], tokenInOutMarket[1], tokenAmountIn, amountsInOutMaxFee[1], block.timestamp, inRecord.balance, outRecord.balance, spotPriceAfter ); _pullUnderlying(tokenInOutMarket[0], msg.sender, tokenAmountIn); uint256 consumeMarketFeeAmount = bsub( tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, amountsInOutMaxFee[3])) ); if (amountsInOutMaxFee[3] > 0) { IERC20(tokenInOutMarket[0]).safeTransfer( tokenInOutMarket[2],// market address consumeMarketFeeAmount ); emit ConsumeMarketFee( tokenInOutMarket[2], // to (market address) tokenInOutMarket[0], // token consumeMarketFeeAmount ); } _pushUnderlying(tokenInOutMarket[1], msg.sender, amountsInOutMaxFee[1]); return (tokenAmountIn, spotPriceAfter); } /** * @dev joinswapExternAmountIn * Single side add liquidity to the pool, * expecting a minPoolAmountOut of shares for spending tokenAmountIn basetokens * @param tokenAmountIn exact number of base tokens to spend * @param minPoolAmountOut minimum of pool shares expectex */ function joinswapExternAmountIn( uint256 tokenAmountIn, uint256 minPoolAmountOut ) external _lock_ returns (uint256 poolAmountOut) { //tokenIn = _baseTokenAddress; require(_finalized, "ERR_NOT_FINALIZED"); _checkBound(_baseTokenAddress); require( tokenAmountIn <= bmul(_records[_baseTokenAddress].balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO" ); //ask ssContract Record storage inRecord = _records[_baseTokenAddress]; poolAmountOut = calcPoolOutGivenSingleIn( inRecord.balance, _totalSupply, tokenAmountIn ); require(poolAmountOut >= minPoolAmountOut, "ERR_LIMIT_OUT"); inRecord.balance = badd(inRecord.balance, tokenAmountIn); emit LOG_JOIN(msg.sender, _baseTokenAddress, tokenAmountIn, block.timestamp); emit LOG_BPT(poolAmountOut); //ask the ssContract to stake as well //calculate how much should the 1ss stake Record storage ssInRecord = _records[_datatokenAddress]; uint256 ssAmountIn = calcSingleInGivenPoolOut( ssInRecord.balance, _totalSupply, poolAmountOut ); if (ssContract.canStake(_datatokenAddress, ssAmountIn)) { //call 1ss to approve ssContract.Stake(_datatokenAddress, ssAmountIn); // follow the same path ssInRecord.balance = badd(ssInRecord.balance, ssAmountIn); emit LOG_JOIN( _controller, _datatokenAddress, ssAmountIn, block.timestamp ); emit LOG_BPT_SS(poolAmountOut); _mintPoolShare(poolAmountOut); _pushPoolShare(_controller, poolAmountOut); _pullUnderlying(_datatokenAddress, _controller, ssAmountIn); } _mintPoolShare(poolAmountOut); _pushPoolShare(msg.sender, poolAmountOut); _pullUnderlying(_baseTokenAddress, msg.sender, tokenAmountIn); return poolAmountOut; } /** * @dev exitswapPoolAmountIn * Single side remove liquidity from the pool, * expecting a minAmountOut of basetokens for spending poolAmountIn pool shares * @param poolAmountIn exact number of pool shares to spend * @param minAmountOut minimum amount of basetokens expected */ function exitswapPoolAmountIn( uint256 poolAmountIn, uint256 minAmountOut ) external _lock_ returns (uint256 tokenAmountOut) { //tokenOut = _baseTokenAddress; require(_finalized, "ERR_NOT_FINALIZED"); _checkBound(_baseTokenAddress); Record storage outRecord = _records[_baseTokenAddress]; tokenAmountOut = calcSingleOutGivenPoolIn( outRecord.balance, _totalSupply, poolAmountIn ); require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT"); require( tokenAmountOut <= bmul(_records[_baseTokenAddress].balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO" ); outRecord.balance = bsub(outRecord.balance, tokenAmountOut); //uint256 exitFee = bmul(poolAmountIn, EXIT_FEE); emit LOG_EXIT(msg.sender, _baseTokenAddress, tokenAmountOut, block.timestamp); emit LOG_BPT(poolAmountIn); //ask the ssContract to unstake as well //calculate how much should the 1ss unstake if ( ssContract.canUnStake(_datatokenAddress, poolAmountIn) ) { Record storage ssOutRecord = _records[_datatokenAddress]; uint256 ssAmountOut = calcSingleOutGivenPoolIn( ssOutRecord.balance, _totalSupply, poolAmountIn ); ssOutRecord.balance = bsub(ssOutRecord.balance, ssAmountOut); //exitFee = bmul(poolAmountIn, EXIT_FEE); emit LOG_EXIT( _controller, _datatokenAddress, ssAmountOut, block.timestamp ); _pullPoolShare(_controller, poolAmountIn); //_burnPoolShare(bsub(poolAmountIn, exitFee)); _burnPoolShare(poolAmountIn); //_pushPoolShare(_factory, exitFee); _pushUnderlying(_datatokenAddress, _controller, ssAmountOut); //call unstake on 1ss to do cleanup on their side ssContract.UnStake( _datatokenAddress, ssAmountOut, poolAmountIn ); emit LOG_BPT_SS(poolAmountIn); } _pullPoolShare(msg.sender, poolAmountIn); //_burnPoolShare(bsub(poolAmountIn, exitFee)); _burnPoolShare(poolAmountIn); //_pushPoolShare(_factory, exitFee); _pushUnderlying(_baseTokenAddress, msg.sender, tokenAmountOut); return tokenAmountOut; } /** * @dev calcSingleOutPoolIn * Returns expected amount of tokenOut for removing exact poolAmountIn pool shares from the pool * @param tokenOut tokenOut * @param poolAmountIn amount of shares spent */ function calcSingleOutPoolIn(address tokenOut, uint256 poolAmountIn) external view returns (uint256 tokenAmountOut) { Record memory outRecord = _records[tokenOut]; tokenAmountOut = calcSingleOutGivenPoolIn( outRecord.balance, _totalSupply, poolAmountIn ); return tokenAmountOut; } /** * @dev calcPoolInSingleOut * Returns number of poolshares needed to withdraw exact tokenAmountOut tokens * @param tokenOut tokenOut * @param tokenAmountOut expected amount of tokensOut */ function calcPoolInSingleOut(address tokenOut, uint256 tokenAmountOut) external view returns (uint256 poolAmountIn) { Record memory outRecord = _records[tokenOut]; poolAmountIn = calcPoolInGivenSingleOut( outRecord.balance, _totalSupply, tokenAmountOut ); return poolAmountIn; } /** * @dev calcSingleInPoolOut * Returns number of tokens to be staked to the pool in order to get an exact number of poolshares * @param tokenIn tokenIn * @param poolAmountOut expected amount of pool shares */ function calcSingleInPoolOut(address tokenIn, uint256 poolAmountOut) external view returns (uint256 tokenAmountIn) { Record memory inRecord = _records[tokenIn]; tokenAmountIn = calcSingleInGivenPoolOut( inRecord.balance, _totalSupply, poolAmountOut ); return tokenAmountIn; } /** * @dev calcPoolOutSingleIn * Returns number of poolshares obtain by staking exact tokenAmountIn tokens * @param tokenIn tokenIn * @param tokenAmountIn exact number of tokens staked */ function calcPoolOutSingleIn(address tokenIn, uint256 tokenAmountIn) external view returns (uint256 poolAmountOut) { Record memory inRecord = _records[tokenIn]; poolAmountOut = calcPoolOutGivenSingleIn( inRecord.balance, _totalSupply, tokenAmountIn ); return poolAmountOut; } // Internal functions below // == // 'Underlying' token-manipulation functions make external calls but are NOT locked // You must `_lock_` or otherwise ensure reentry-safety function _pullUnderlying( address erc20, address from, uint256 amount ) internal { uint256 balanceBefore = IERC20(erc20).balanceOf(address(this)); IERC20(erc20).safeTransferFrom(from, address(this), amount); require(IERC20(erc20).balanceOf(address(this)) >= balanceBefore + amount, "Transfer amount is too low"); //require(xfer, "ERR_ERC20_FALSE"); } function _pushUnderlying( address erc20, address to, uint256 amount ) internal { IERC20(erc20).safeTransfer(to, amount); //require(xfer, "ERR_ERC20_FALSE"); } function _pullPoolShare(address from, uint256 amount) internal { _pull(from, amount); } function _pushPoolShare(address to, uint256 amount) internal { _push(to, amount); } function _mintPoolShare(uint256 amount) internal { _mint(amount); } function _burnPoolShare(uint256 amount) internal { _burn(amount); } // Absorb any tokens that have been sent to this contract into the pool function gulp(address token) external _lock_ { require(_records[token].bound, "ERR_NOT_BOUND"); uint256 oldBalance = _records[token].balance; _records[token].balance = IERC20(token).balanceOf(address(this)); emit Gulped(token,oldBalance, _records[token].balance); } }
// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.8.12; // Copyright Balancer, BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 contract BConst { uint public constant BONE = 1e18; uint public constant MIN_BOUND_TOKENS = 2; uint public constant MAX_BOUND_TOKENS = 2; uint public constant MIN_FEE = BONE / 1e4; uint public constant MAX_FEE = BONE / 10; uint public constant EXIT_FEE = 0; uint public constant MIN_WEIGHT = BONE; uint public constant MAX_WEIGHT = BONE * 50; uint public constant MAX_TOTAL_WEIGHT = BONE * 50; uint public constant MIN_BALANCE = BONE / 1e12; uint public constant INIT_POOL_SUPPLY = BONE * 100; uint public constant MIN_BPOW_BASE = 1 wei; uint public constant MAX_BPOW_BASE = (2 * BONE) - 1 wei; uint public constant BPOW_PRECISION = BONE / 1e10; uint public constant MAX_IN_RATIO = BONE / 2; uint public constant MAX_OUT_RATIO = (BONE / 2) + 1 wei; }
pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 /** * @title Deployer Contract * @author Ocean Protocol Team * * @dev Contract Deployer * This contract allowes factory contract * to deploy new contract instances using * the same library pattern in solidity. * the logic it self is deployed only once, but * executed in the context of the new storage * contract (new contract instance) */ contract Deployer { event InstanceDeployed(address instance); // /** // * @dev deploy // * deploy new contract instance // * @param _logic the logic contract address // * @return address of the new instance // */ function deploy( address _logic ) internal returns (address instance) { bytes20 targetBytes = bytes20(_logic); // solhint-disable-next-line max-line-length // Follows OpenZeppelin Implementation https://github.com/OpenZeppelin/openzeppelin-sdk/blob/71c9ad77e0326db079e6a643eca8568ab316d4a9/packages/lib/contracts/upgradeability/ProxyFactory.sol // solhint-disable-next-line max-line-length // Adapted from https://github.com/optionality/clone-factory/blob/32782f82dfc5a00d103a7e61a17a5dedbd1e8e9d/contracts/CloneFactory.sol /* solium-disable-next-line security/no-inline-assembly */ assembly { let clone := mload(0x40) mstore(clone, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000) mstore(add(clone, 0x14), targetBytes) mstore(add(clone, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000) instance := create(0, clone, 0x37) } emit InstanceDeployed(address(instance)); } }
// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 interface ISideStaking { function newDatatokenCreated( address datatokenAddress, address baseTokenAddress, address poolAddress, address publisherAddress, uint256[] calldata ssParams ) external returns (bool); function getDatatokenCirculatingSupply(address datatokenAddress) external view returns (uint256); function getPublisherAddress(address datatokenAddress) external view returns (address); function getBaseTokenAddress(address datatokenAddress) external view returns (address); function getPoolAddress(address datatokenAddress) external view returns (address); function getBaseTokenBalance(address datatokenAddress) external view returns (uint256); function getDatatokenBalance(address datatokenAddress) external view returns (uint256); function getvestingEndBlock(address datatokenAddress) external view returns (uint256); function getvestingAmount(address datatokenAddress) external view returns (uint256); function getvestingLastBlock(address datatokenAddress) external view returns (uint256); function getvestingAmountSoFar(address datatokenAddress) external view returns (uint256); function canStake( address datatokenAddress, uint256 amount ) external view returns (bool); function Stake( address datatokenAddress, uint256 amount ) external; function canUnStake( address datatokenAddress, uint256 amount ) external view returns (bool); function UnStake( address datatokenAddress, uint256 amount, uint256 poolAmountIn ) external; function getId() pure external returns (uint8); }
// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.8.12; // Copyright Balancer, BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 import './BNum.sol'; // import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '../../interfaces/IERC20.sol'; // Highly opinionated token implementation // interface IERC20 { // event Approval(address indexed src, address indexed dst, uint amt); // event Transfer(address indexed src, address indexed dst, uint amt); // function totalSupply() external view returns (uint); // function balanceOf(address whom) external view returns (uint); // function allowance(address src, address dst) external view returns (uint); // function approve(address dst, uint amt) external returns (bool); // function transfer(address dst, uint amt) external returns (bool); // function transferFrom( // address src, address dst, uint amt // ) external returns (bool); // } contract BTokenBase is BNum { mapping(address => uint) internal _balance; mapping(address => mapping(address=>uint)) internal _allowance; uint internal _totalSupply; event Approval(address indexed src, address indexed dst, uint amt); event Transfer(address indexed src, address indexed dst, uint amt); function _mint(uint amt) internal { _balance[address(this)] = badd(_balance[address(this)], amt); _totalSupply = badd(_totalSupply, amt); emit Transfer(address(0), address(this), amt); } function _burn(uint amt) internal { require( _balance[address(this)] >= amt, 'ERR_INSUFFICIENT_BAL' ); _balance[address(this)] = bsub(_balance[address(this)], amt); _totalSupply = bsub(_totalSupply, amt); emit Transfer(address(this), address(0), amt); } function _move(address src, address dst, uint amt) internal { require(_balance[src] >= amt, 'ERR_INSUFFICIENT_BAL'); _balance[src] = bsub(_balance[src], amt); _balance[dst] = badd(_balance[dst], amt); emit Transfer(src, dst, amt); } function _push(address to, uint amt) internal { _move(address(this), to, amt); } function _pull(address from, uint amt) internal { _move(from, address(this), amt); } } contract BToken is BTokenBase { function name() external view returns (string memory) { return 'Ocean Pool Token'; } function symbol() external view returns (string memory) { return 'OPT'; } function decimals() external view returns(uint8) { return 18; } function allowance(address src, address dst) external view returns (uint256) { return _allowance[src][dst]; } function balanceOf(address whom) external view returns (uint) { return _balance[whom]; } function totalSupply() public view returns (uint) { return _totalSupply; } function approve(address dst, uint amt) external returns (bool) { _allowance[msg.sender][dst] = amt; emit Approval(msg.sender, dst, amt); return true; } function increaseApproval(address dst, uint amt) external returns (bool) { _allowance[msg.sender][dst] = badd(_allowance[msg.sender][dst], amt); emit Approval(msg.sender, dst, _allowance[msg.sender][dst]); return true; } function decreaseApproval(address dst, uint amt) external returns (bool) { uint oldValue = _allowance[msg.sender][dst]; if (amt > oldValue) { _allowance[msg.sender][dst] = 0; } else { _allowance[msg.sender][dst] = bsub(oldValue, amt); } emit Approval(msg.sender, dst, _allowance[msg.sender][dst]); return true; } function transfer(address dst, uint amt) external returns (bool) { _move(msg.sender, dst, amt); return true; } function transferFrom( address src, address dst, uint amt ) external returns (bool) { require( msg.sender == src || amt <= _allowance[src][msg.sender], 'ERR_BTOKEN_BAD_CALLER' ); _move(src, dst, amt); if (msg.sender != src && _allowance[src][msg.sender] != uint256(int(-1)) ) { _allowance[src][msg.sender] = bsub(_allowance[src][msg.sender], amt); emit Approval(src, msg.sender, _allowance[src][msg.sender]); } return true; } }
// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.8.12; // Copyright Balancer, BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 import './BNum.sol'; import "../../interfaces/IFactoryRouter.sol"; contract BMath is BConst, BNum { // uint public _swapMarketFee; uint public _swapPublishMarketFee; uint internal _swapFee; address public router; // BFactory address to push token exitFee to address internal _datatokenAddress; //datatoken address address internal _baseTokenAddress; //base token address mapping(address => uint) public communityFees; mapping(address => uint) public publishMarketFees; // mapping(address => uint) public marketFees; function getOPCFee() public view returns (uint) { return IFactoryRouter(router).getOPCFee(_baseTokenAddress); } struct swapfees{ uint256 LPFee; uint256 oceanFeeAmount; uint256 publishMarketFeeAmount; uint256 consumeMarketFee; } /********************************************************************************************** // calcSpotPrice // // sP = spotPrice // // bI = tokenBalanceIn ( bI / wI ) 1 // // bO = tokenBalanceOut sP = ----------- * ---------- // // wI = tokenWeightIn ( bO / wO ) ( 1 - sF ) // // wO = tokenWeightOut // // sF = swapFee // **********************************************************************************************/ function calcSpotPrice( uint tokenBalanceIn, uint tokenWeightIn, uint tokenBalanceOut, uint tokenWeightOut, uint _swapMarketFee ) internal view returns (uint spotPrice) { uint numer = bdiv(tokenBalanceIn, tokenWeightIn); uint denom = bdiv(tokenBalanceOut, tokenWeightOut); uint ratio = bdiv(numer, denom); uint scale = bdiv(BONE, bsub(BONE, _swapFee+getOPCFee()+_swapPublishMarketFee+_swapMarketFee)); return (spotPrice = bmul(ratio, scale)); } // data = [ // inRecord.balance, // inRecord.denorm, // outRecord.balance, // outRecord.denorm // ]; function calcOutGivenIn( uint[4] memory data, uint tokenAmountIn, //address tokenInAddress, uint256 _consumeMarketSwapFee ) public view returns (uint tokenAmountOut, uint balanceInToAdd, swapfees memory _swapfees) { uint weightRatio = bdiv(data[1], data[3]); _swapfees.oceanFeeAmount = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, getOPCFee()))); _swapfees.publishMarketFeeAmount = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, _swapPublishMarketFee))); _swapfees.LPFee = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, _swapFee))); _swapfees.consumeMarketFee = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, _consumeMarketSwapFee))); uint totalFee =_swapFee+getOPCFee()+_swapPublishMarketFee+_consumeMarketSwapFee; uint adjustedIn = bsub(BONE, totalFee); adjustedIn = bmul(tokenAmountIn, adjustedIn); uint y = bdiv(data[0], badd(data[0], adjustedIn)); uint foo = bpow(y, weightRatio); uint bar = bsub(BONE, foo); tokenAmountOut = bmul(data[2], bar); return (tokenAmountOut, bsub(tokenAmountIn,(_swapfees.oceanFeeAmount+_swapfees.publishMarketFeeAmount+_swapfees.consumeMarketFee)), _swapfees); } function calcInGivenOut( uint[4] memory data, uint tokenAmountOut, uint _consumeMarketSwapFee ) public view returns (uint tokenAmountIn, uint tokenAmountInBalance, swapfees memory _swapfees) { uint weightRatio = bdiv(data[3], data[1]); uint diff = bsub(data[2], tokenAmountOut); uint y = bdiv(data[2], diff); uint foo = bpow(y, weightRatio); foo = bsub(foo, BONE); uint totalFee =_swapFee+getOPCFee()+_consumeMarketSwapFee+_swapPublishMarketFee; tokenAmountIn = bdiv(bmul(data[0], foo), bsub(BONE, totalFee)); _swapfees.oceanFeeAmount = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, getOPCFee()))); _swapfees.publishMarketFeeAmount = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, _swapPublishMarketFee))); _swapfees.LPFee = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, _swapFee))); _swapfees.consumeMarketFee = bsub(tokenAmountIn, bmul(tokenAmountIn, bsub(BONE, _consumeMarketSwapFee))); tokenAmountInBalance = bsub(tokenAmountIn,(_swapfees.oceanFeeAmount+_swapfees.publishMarketFeeAmount+_swapfees.consumeMarketFee)); return (tokenAmountIn, tokenAmountInBalance,_swapfees); } function calcPoolOutGivenSingleIn( uint tokenBalanceIn, uint poolSupply, uint tokenAmountIn ) internal pure returns (uint poolAmountOut) { uint tokenAmountInAfterFee = bmul(tokenAmountIn, BONE); uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee); uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn); uint poolRatio = bsub(tokenInRatio,BONE); uint newPoolSupply = bmul(poolRatio, poolSupply); require(newPoolSupply >= 2, 'ERR_TOKEN_AMOUNT_IN_TOO_LOW'); newPoolSupply = newPoolSupply/2; return newPoolSupply; } function calcSingleInGivenPoolOut( uint tokenBalanceIn, uint poolSupply, uint poolAmountOut ) internal pure returns (uint tokenAmountIn) { uint newPoolSupply = badd(poolSupply, poolAmountOut); uint poolRatio = bdiv(newPoolSupply, poolSupply); uint tokenInRatio = bsub(poolRatio, BONE); uint newTokenBalanceIn = bmul(tokenInRatio, tokenBalanceIn); require(newTokenBalanceIn >= 1, 'ERR_POOL_AMOUNT_OUT_TOO_LOW'); newTokenBalanceIn = newTokenBalanceIn * 2; return newTokenBalanceIn; } function calcSingleOutGivenPoolIn( uint tokenSupply, uint poolSupply, uint poolAmountIn ) internal pure returns (uint tokenAmountOut) { require(poolAmountIn >= 1, 'ERR_POOL_AMOUNT_IN_TOO_LOW'); poolAmountIn = poolAmountIn * 2; uint newPoolSupply = bsub(poolSupply, poolAmountIn); uint poolRatio = bdiv(newPoolSupply, poolSupply); uint tokenOutRatio = bsub(BONE,poolRatio); uint newTokenBalanceOut = bmul(tokenOutRatio, tokenSupply); return newTokenBalanceOut; } function calcPoolInGivenSingleOut( uint tokenBalanceOut, uint poolSupply, uint tokenAmountOut ) internal pure returns (uint poolAmountIn) { uint newTokenBalanceOut = bsub( tokenBalanceOut, tokenAmountOut ); uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut); uint poolRatio = bsub(BONE,tokenOutRatio); uint newPoolSupply = bmul(poolRatio, poolSupply); require(newPoolSupply >= 2, 'ERR_TOKEN_AMOUNT_OUT_TOO_LOW'); newPoolSupply = newPoolSupply/2; return newPoolSupply; } }
// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. pragma solidity 0.8.12; // Copyright Balancer, BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 import './BConst.sol'; contract BNum is BConst { function btoi(uint a) internal pure returns (uint) { return a / BONE; } function bfloor(uint a) internal pure returns (uint) { return btoi(a) * BONE; } function badd(uint a, uint b) internal pure returns (uint) { uint c = a + b; require(c >= a, 'ERR_ADD_OVERFLOW'); return c; } function bsub(uint a, uint b) internal pure returns (uint) { (uint c, bool flag) = bsubSign(a, b); require(!flag, 'ERR_SUB_UNDERFLOW'); return c; } function bsubSign(uint a, uint b) internal pure returns (uint, bool) { if (a >= b) { return (a - b, false); } else { return (b - a, true); } } function bmul(uint a, uint b) internal pure returns (uint) { uint c0 = a * b; require(a == 0 || c0 / a == b, 'ERR_MUL_OVERFLOW'); uint c1 = c0 + (BONE / 2); require(c1 >= c0, 'ERR_MUL_OVERFLOW'); uint c2 = c1 / BONE; return c2; } function bdiv(uint a, uint b) internal pure returns (uint) { require(b != 0, 'ERR_DIV_ZERO'); uint c0 = a * BONE; require(a == 0 || c0 / a == BONE, 'ERR_DIV_INTERNAL'); // bmul overflow uint c1 = c0 + (b / 2); require(c1 >= c0, 'ERR_DIV_INTERNAL'); // badd require uint c2 = c1 / b; return c2; } // DSMath.wpow function bpowi(uint a, uint n) internal pure returns (uint) { uint b = a; uint z = n % 2 != 0 ? b : BONE; for (n /= 2; n != 0; n /= 2) { b = bmul(b, b); if (n % 2 != 0) { z = bmul(z, b); } } return z; } // Compute b^(e.w) by splitting it into (b^e)*(b^0.w). // Use `bpowi` for `b^e` and `bpowK` for k iterations // of approximation of b^0.w function bpow(uint base, uint exp) internal pure returns (uint) { require(base >= MIN_BPOW_BASE, 'ERR_BPOW_BASE_TOO_LOW'); require(base <= MAX_BPOW_BASE, 'ERR_BPOW_BASE_TOO_HIGH'); uint whole = bfloor(exp); uint remain = bsub(exp, whole); uint wholePow = bpowi(base, btoi(whole)); if (remain == 0) { return wholePow; } uint partialResult = bpowApprox(base, remain, BPOW_PRECISION); return bmul(wholePow, partialResult); } function bpowApprox(uint base, uint exp, uint precision) internal pure returns (uint) { // term 0: uint a = exp; (uint x, bool xneg) = bsubSign(base, BONE); uint term = BONE; uint sum = term; bool negative = false; // term(k) = numer / denom // = (product(a - i - 1, i=1-->k) * x^k) / (k!) // each iteration, multiply previous term by (a-(k-1)) * x / k // continue until term is less than precision for (uint i = 1; term >= precision; i++) { uint bigK = i * BONE; (uint c, bool cneg) = bsubSign(a, bsub(bigK, BONE)); term = bmul(term, bmul(c, x)); term = bdiv(term, bigK); if (term == 0) break; if (xneg) negative = !negative; if (cneg) negative = !negative; if (negative) { sum = bsub(sum, term); } else { sum = badd(sum, term); } } return sum; } }
pragma solidity 0.8.12; // Copyright BigchainDB GmbH and Ocean Protocol contributors // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) // Code is Apache-2.0 and docs are CC-BY-4.0 interface IFactoryRouter { function deployPool( address[2] calldata tokens, // [datatokenAddress, baseTokenAddress] uint256[] calldata ssParams, uint256[] calldata swapFees, address[] calldata addresses ) external returns (address); function deployFixedRate( address fixedPriceAddress, address[] calldata addresses, uint256[] calldata uints ) external returns (bytes32 exchangeId); function getOPCFee(address baseToken) external view returns (uint256); function getOPCFees() external view returns (uint256,uint256); function getOPCConsumeFee() external view returns (uint256); function getOPCProviderFee() external view returns (uint256); function getMinVestingPeriod() external view returns (uint256); function deployDispenser( address _dispenser, address datatoken, uint256 maxTokens, uint256 maxBalance, address owner, address allowedSwapper ) external; function isApprovedToken(address) external view returns(bool); function getApprovedTokens() external view returns(address[] memory); function isSSContract(address) external view returns(bool); function getSSContracts() external view returns(address[] memory); function isFixedRateContract(address) external view returns(bool); function getFixedRatesContracts() external view returns(address[] memory); function isDispenserContract(address) external view returns(bool); function getDispensersContracts() external view returns(address[] memory); function isPoolTemplate(address) external view returns(bool); function getPoolTemplates() external view returns(address[] memory); struct Stakes { address poolAddress; uint256 tokenAmountIn; uint256 minPoolAmountOut; } function stakeBatch(Stakes[] calldata) external; enum operationType { SwapExactIn, SwapExactOut, FixedRate, Dispenser } struct Operations { bytes32 exchangeIds; // used for fixedRate or dispenser address source; // pool, dispenser or fixed rate address operationType operation; // type of operation: enum operationType address tokenIn; // token in address, only for pools uint256 amountsIn; // ExactAmount In for swapExactIn operation, maxAmount In for swapExactOut address tokenOut; // token out address, only for pools uint256 amountsOut; // minAmountOut for swapExactIn or exactAmountOut for swapExactOut uint256 maxPrice; // maxPrice, only for pools uint256 swapMarketFee; address marketFeeAddress; } function buyDTBatch(Operations[] calldata) external; function updateOPCCollector(address _opcCollector) external; function getOPCCollector() view external returns (address); }
pragma solidity 0.8.12; // SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0) /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } /** * @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @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, it is bubbled up by this * function (like regular Solidity function calls). * * 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. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @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`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); } function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // 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 // solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } } // File @openzeppelin/contracts/utils/[email protected]
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_routerOwner","type":"address"},{"internalType":"address","name":"_oceanToken","type":"address"},{"internalType":"address","name":"_bpoolTemplate","type":"address"},{"internalType":"address","name":"_opcCollector","type":"address"},{"internalType":"address[]","name":"_preCreatedPools","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newBPoolAddress","type":"address"},{"indexed":true,"internalType":"address","name":"registeredBy","type":"address"},{"indexed":true,"internalType":"address","name":"datatokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"baseTokenAddress","type":"address"},{"indexed":false,"internalType":"address","name":"bpoolTemplateAddress","type":"address"},{"indexed":false,"internalType":"address","name":"ssAddress","type":"address"}],"name":"BPoolCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"DispenserContractAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"DispenserContractRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"FactoryContractChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"FixedRateContractAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"FixedRateContractRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"instance","type":"address"}],"name":"InstanceDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"poolAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"isOcean","type":"bool"}],"name":"NewPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"_newOpcCollector","type":"address"}],"name":"OPCCollectorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"newSwapOceanFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newSwapNonOceanFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newConsumeFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newProviderFee","type":"uint256"}],"name":"OPCFeeChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"PoolTemplateAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"PoolTemplateRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"newRouter","type":"address"}],"name":"RouterChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"SSContractAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"contractAddress","type":"address"}],"name":"SSContractRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"}],"name":"TokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"uint256","name":"minVestingPeriodInBlocks","type":"uint256"}],"name":"VestingPeriodChanges","type":"event"},{"inputs":[],"name":"BONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BPOW_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXIT_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INIT_POOL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_IN_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OUT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TOTAL_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BALANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"addApprovedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_dispenser","type":"address"}],"name":"addDispenserContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"addFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fixedRate","type":"address"}],"name":"addFixedRateContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"poolTemplate","type":"address"}],"name":"addPoolTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ssContract","type":"address"}],"name":"addSSContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"approvedTokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"exchangeIds","type":"bytes32"},{"internalType":"address","name":"source","type":"address"},{"internalType":"enum IFactoryRouter.operationType","name":"operation","type":"uint8"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountsIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountsOut","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"},{"internalType":"uint256","name":"swapMarketFee","type":"uint256"},{"internalType":"address","name":"marketFeeAddress","type":"address"}],"internalType":"struct IFactoryRouter.Operations[]","name":"_operations","type":"tuple[]"}],"name":"buyDTBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_routerOwner","type":"address"}],"name":"changeRouterOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"consumeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_dispenser","type":"address"},{"internalType":"address","name":"datatoken","type":"address"},{"internalType":"uint256","name":"maxTokens","type":"uint256"},{"internalType":"uint256","name":"maxBalance","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"allowedSwapper","type":"address"}],"name":"deployDispenser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"fixedPriceAddress","type":"address"},{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint256[]","name":"uints","type":"uint256[]"}],"name":"deployFixedRate","outputs":[{"internalType":"bytes32","name":"exchangeId","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[2]","name":"tokens","type":"address[2]"},{"internalType":"uint256[]","name":"ssParams","type":"uint256[]"},{"internalType":"uint256[]","name":"swapFees","type":"uint256[]"},{"internalType":"address[]","name":"addresses","type":"address[]"}],"name":"deployPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"dispensers","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fixedRate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"fixedrates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getApprovedTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDispensersContracts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFixedRatesContracts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinVestingPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOPCCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOPCConsumeFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"baseToken","type":"address"}],"name":"getOPCFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOPCFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOPCProviderFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolTemplates","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSSContracts","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"isApprovedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_dispenser","type":"address"}],"name":"isDispenserContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_fixedRate","type":"address"}],"name":"isFixedRateContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"poolTemplate","type":"address"}],"name":"isPoolTemplate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_ssContract","type":"address"}],"name":"isSSContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minVestingPeriodInBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"opcCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"poolTemplates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"providerFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"}],"name":"removeApprovedToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_dispenser","type":"address"}],"name":"removeDispenserContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_fixedRate","type":"address"}],"name":"removeFixedRateContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"poolTemplate","type":"address"}],"name":"removePoolTemplate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ssContract","type":"address"}],"name":"removeSSContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"routerOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"ssContracts","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"poolAddress","type":"address"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"minPoolAmountOut","type":"uint256"}],"internalType":"struct IFactoryRouter.Stakes[]","name":"_stakes","type":"tuple[]"}],"name":"stakeBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapNonOceanFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapOceanFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPeriod","type":"uint256"}],"name":"updateMinVestingPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_opcCollector","type":"address"}],"name":"updateOPCCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newSwapOceanFee","type":"uint256"},{"internalType":"uint256","name":"_newSwapNonOceanFee","type":"uint256"},{"internalType":"uint256","name":"_newConsumeFee","type":"uint256"},{"internalType":"uint256","name":"_newProviderFee","type":"uint256"}],"name":"updateOPCFee","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040526225049060055566038d7ea4c6800060065566071afd498d0000600755666a94d74f43000060085560006009553480156200003e57600080fd5b5060405162004ee938038062004ee983398101604081905262000061916200062d565b8282826001600160a01b038316620000d65760405162461bcd60e51b815260206004820152602d60248201527f42466163746f72793a20696e76616c69642062706f6f6c2074656d706c61746560448201526c207a65726f206164647265737360981b60648201526084015b60405180910390fd5b6001600160a01b0382166200012e5760405162461bcd60e51b815260206004820152601660248201527f42466163746f72793a207a65726f2061646472657373000000000000000000006044820152606401620000cd565b600080546001600160a01b0319166001600160a01b03841617905562000154836200037f565b805115620002035760005b8151811015620002015760006001600160a01b0316336001600160a01b03168383815181106200019357620001936200074d565b602090810291909101810151604080516000808252938101849052908101929092526001600160a01b0316907fbb6121447d29a04cc37bfd93cdf6a9dd08229f2d941116c1528f04698c4e790e9060600160405180910390a480620001f88162000763565b9150506200015f565b505b5050506001600160a01b0385166200026a5760405162461bcd60e51b815260206004820152602360248201527f466163746f7279526f757465723a20496e76616c696420726f75746572206f776044820152623732b960e91b6064820152608401620000cd565b6001600160a01b038216620002ce5760405162461bcd60e51b815260206004820152602360248201527f466163746f7279526f757465723a20496e76616c6964206f7063436f6c6c65636044820152623a37b960e91b6064820152608401620000cd565b6001600160a01b038416620003395760405162461bcd60e51b815260206004820152602a60248201527f466163746f7279526f757465723a20496e76616c6964204f6365616e20546f6b604482015269656e206164647265737360b01b6064820152608401620000cd565b600280546001600160a01b038088166001600160a01b0319928316179092556000805492851692909116919091179055620003748462000476565b50505050506200078d565b6001600160a01b038116620003eb5760405162461bcd60e51b815260206004820152602b60248201527f466163746f7279526f757465723a20496e76616c696420706f6f6c54656d706c60448201526a617465206164647265737360a81b6064820152608401620000cd565b620003f68162000501565b620004735760018054808201825560009182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b038416908117909155604051909133917fc3674c32cbec94fe266aab7ef71f65b9bf77e1ed501d4f2bece8752f5352e9ac9190a35b50565b62000481816200051f565b6200047357600a805460018101825560009182527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b0319166001600160a01b038416908117909155604051909133917fdffbd9ded1c09446f09377de547142dcce7dc541c8b0b028142b1eba7026b9e79190a350565b600062000519826200059160201b620030361760201c565b92915050565b6000805b600a548110156200058857826001600160a01b0316600a82815481106200054e576200054e6200074d565b6000918252602090912001546001600160a01b03161415620005735750600192915050565b806200057f8162000763565b91505062000523565b50600092915050565b6000805b6001548110156200058857826001600160a01b031660018281548110620005c057620005c06200074d565b6000918252602090912001546001600160a01b03161415620005e55750600192915050565b80620005f18162000763565b91505062000595565b80516001600160a01b03811681146200061257600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a086880312156200064657600080fd5b6200065186620005fa565b9450602062000662818801620005fa565b94506200067260408801620005fa565b93506200068260608801620005fa565b60808801519093506001600160401b0380821115620006a057600080fd5b818901915089601f830112620006b557600080fd5b815181811115620006ca57620006ca62000617565b8060051b604051601f19603f83011681018181108582111715620006f257620006f262000617565b60405291825284820192508381018501918c8311156200071157600080fd5b938501935b828510156200073a576200072a85620005fa565b8452938501939285019262000716565b8096505050505050509295509295909350565b634e487b7160e01b600052603260045260246000fd5b60006000198214156200078657634e487b7160e01b600052601160045260246000fd5b5060010190565b61474c806200079d6000396000f3fe608060405234801561001057600080fd5b50600436106103e65760003560e01c8063858ab5961161020a578063c45a015511610125578063e183fb3f116100b8578063e525f99c11610087578063e525f99c14610782578063ec09302114610795578063ecdda5881461079d578063ee3bc635146107b0578063fca24bc6146107c357600080fd5b8063e183fb3f1461075d578063e193faad14610766578063e2bdeefa14610779578063e4a28a521461041b57600080fd5b8063cd10534b116100f4578063cd10534b14610709578063d629a00a1461071c578063dce2d0df1461072f578063de9a95a71461074a57600080fd5b8063c45a0155146106dc578063c6580d12146106ef578063c6e983d9146106f7578063cb870cbf1461070057600080fd5b8063b7b800a41161019d578063bc694ea21161016c578063bc694ea2146106ae578063bfa04b85146106b6578063c07c00fe146106c9578063c36596a6146104bd57600080fd5b8063b7b800a41461065d578063b8421e2b1461068b578063ba019dab1461069e578063bc063e1a146106a657600080fd5b80639f2c010a116101d95780639f2c010a1461064a578063b0e0d1361461065d578063b19aaac614610665578063b66806fb1461067857600080fd5b8063858ab5961461061f578063867378c5146106325780639381cd2b1461063a578063992e2a921461064257600080fd5b8063475030c0116103055780636cdf90a1116102985780637cbf85bf116102675780637cbf85bf146105cb5780637d28354d146105de578063802d1422146105e657806382449375146105f95780638552730a1461060c57600080fd5b80636cdf90a114610595578063737e5ca0146105a85780637521aff9146105b057806376c7a3c7146105c357600080fd5b80635705987a116102d45780635705987a1461055f5780636afc0c5f146105725780636c45e8811461057a5780636c9fb6121461058257600080fd5b8063475030c01461052857806347e140941461053157806350cbbe7614610544578063510f34651461055757600080fd5b80631dafede01161037d5780632d5ad3d51161034c5780632d5ad3d5146104e7578063335b7fa2146104fa578063415792081461050d57806346104ea81461052057600080fd5b80631dafede0146104aa578063218b5382146104bd578063241c7a6d146104cc57806329ce1ec5146104d457600080fd5b806316592614116103b9578063165926141461046957806316d9cb3d1461047e578063189d00ca146104915780631a81876d1461049957600080fd5b806303814238146103eb57806309a3bbe41461041b57806315c25dd51461043157806315d4c9eb14610454575b600080fd5b6000546103fe906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6104236107d6565b604051908152602001610412565b61044461043f366004613cc2565b6107ec565b6040519015158152602001610412565b61045c610856565b6040516104129190613cdf565b61047c610477366004613cc2565b6108b8565b005b61047c61048c366004613cc2565b610a60565b610423610b39565b6000546001600160a01b03166103fe565b6103fe6104b8366004613d2c565b610b50565b610423670de0b6b3a764000081565b61045c610b7a565b61047c6104e2366004613cc2565b610b89565b6104446104f5366004613cc2565b610cb4565b6103fe610508366004613d2c565b610d15565b61047c61051b366004613cc2565b610d25565b61045c610dfc565b61042360055481565b61047c61053f366004613cc2565b610e5c565b6103fe610552366004613d2c565b610ffa565b600554610423565b61047c61056d366004613cc2565b61100a565b61045c6111eb565b600954610423565b61047c610590366004613cc2565b61124b565b6104446105a3366004613cc2565b611323565b61045c611384565b61047c6105be366004613d2c565b6113e4565b61042361144b565b6103fe6105d9366004613d2c565b61145f565b600854610423565b6004546103fe906001600160a01b031681565b610423610607366004613d91565b61146f565b6002546103fe906001600160a01b031681565b61047c61062d366004613e14565b6115e1565b6104236119e5565b6104236119fc565b610423611a0f565b61047c610658366004613cc2565b611a2d565b610423600281565b61047c610673366004613cc2565b611bcb565b6103fe610686366004613d2c565b611bfe565b610423610699366004613cc2565b611c0e565b610423600181565b610423611c33565b610423611c46565b61047c6106c4366004613e89565b611c65565b6104446106d7366004613cc2565b611cf3565b6003546103fe906001600160a01b031681565b610423600081565b61042360095481565b61042360075481565b61047c610717366004613cc2565b611d04565b61047c61072a366004613ebb565b611d37565b60065460075460408051928352602083019190915201610412565b61047c610758366004613cc2565b611ea7565b61042360065481565b61047c610774366004613cc2565b611f7f565b61042360085481565b61047c610790366004613cc2565b611fb2565b61042361207e565b61047c6107ab366004613f2b565b612091565b6103fe6107be366004613f8f565b612c33565b6104446107d1366004613cc2565b612fd5565b6107e9670de0b6b3a76400006032614055565b81565b6000805b600b5481101561084d57826001600160a01b0316600b828154811061081757610817614074565b6000918252602090912001546001600160a01b0316141561083b5750600192915050565b806108458161408a565b9150506107f0565b50600092915050565b6060600d8054806020026020016040519081016040528092919081815260200182805480156108ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610890575b5050505050905090565b6002546001600160a01b031633146108eb5760405162461bcd60e51b81526004016108e2906140a5565b60405180910390fd5b6001600160a01b0381166109115760405162461bcd60e51b81526004016108e2906140d5565b60005b600d5481101561096d57816001600160a01b0316600d828154811061093b5761093b614074565b6000918252602090912001546001600160a01b0316141561095b5761096d565b806109658161408a565b915050610914565b600d54811015610a5c57600d80546109879060019061411e565b8154811061099757610997614074565b600091825260209091200154600d80546001600160a01b0390921691839081106109c3576109c3614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600d805480610a0257610a02614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917f63fe522dcdc5f006279afe8840a87398bb3d0dbb906b848866195859621908b39190a35b5050565b6002546001600160a01b03163314610a8a5760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610ab05760405162461bcd60e51b81526004016108e29061414b565b610ab981611323565b610b3657600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319166001600160a01b038416908117909155604051909133917f45ccb9b9d6b112eb7a38daf6a23bda8b4c8449d5cf64a034975a5beb8cdd37b39190a35b50565b6107e96402540be400670de0b6b3a7640000614194565b600a8181548110610b6057600080fd5b6000918252602090912001546001600160a01b0316905081565b6060610b84613097565b905090565b6002546001600160a01b03163314610bb35760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610c195760405162461bcd60e51b815260206004820152602760248201527f466163746f7279526f757465723a20496e76616c6964205f666163746f7279206044820152666164647265737360c81b60648201526084016108e2565b6003546001600160a01b031615610c685760405162461bcd60e51b8152602060048201526013602482015272119050d513d49648105314915051164814d155606a1b60448201526064016108e2565b600380546001600160a01b0319166001600160a01b03831690811790915560405133907f1f869f1ddaa0e2e3652252b3394c05c805f54a0d5f7fb6975f785ae4f91e587190600090a350565b6000805b600a5481101561084d57826001600160a01b0316600a8281548110610cdf57610cdf614074565b6000918252602090912001546001600160a01b03161415610d035750600192915050565b80610d0d8161408a565b915050610cb8565b600d8181548110610b6057600080fd5b6002546001600160a01b03163314610d4f5760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610db15760405162461bcd60e51b8152602060048201526024808201527f4e6577206f7063436f6c6c6563746f722063616e6e6f74206265205a45524f5f60448201526320a2222960e11b60648201526084016108e2565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917fbadc0056fc46a437b2d0a4e9ae17a4f964e18972b5f2455b98b7331c1401a80f9190a350565b6060600c8054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6002546001600160a01b03163314610e865760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610eac5760405162461bcd60e51b81526004016108e2906141b6565b60005b600b54811015610f0857816001600160a01b0316600b8281548110610ed657610ed6614074565b6000918252602090912001546001600160a01b03161415610ef657610f08565b80610f008161408a565b915050610eaf565b600b54811015610a5c57600b8054610f229060019061411e565b81548110610f3257610f32614074565b600091825260209091200154600b80546001600160a01b039092169183908110610f5e57610f5e614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b805480610f9d57610f9d614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917f7df5d17d768be6563796784637c80bc9204e2af0bc4ba8630f5aa2fed96ea4879190a35050565b60018181548110610b6057600080fd5b6002546001600160a01b031633146110345760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b03811661109d5760405162461bcd60e51b815260206004820152602a60248201527f466163746f7279526f757465723a20496e76616c6964204f6365616e20546f6b604482015269656e206164647265737360b01b60648201526084016108e2565b60005b600a548110156110f957816001600160a01b0316600a82815481106110c7576110c7614074565b6000918252602090912001546001600160a01b031614156110e7576110f9565b806110f18161408a565b9150506110a0565b600a54811015610a5c57600a80546111139060019061411e565b8154811061112357611123614074565b600091825260209091200154600a80546001600160a01b03909216918390811061114f5761114f614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a80548061118e5761118e614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917fbbe55b1ff108e23e5ff1a6f5d36946eec15ec0ca0ded2bfed4cdcf697ca904609190a35050565b6060600a8054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6002546001600160a01b031633146112755760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b03811661129b5760405162461bcd60e51b81526004016108e2906141b6565b6112a4816107ec565b610b3657600b805460018101825560009182527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b0319166001600160a01b038416908117909155604051909133917fcef3ce01f85c030161b431114e41e463297b68f169c1013c526b1cbc5747e5449190a350565b6000805b600c5481101561084d57826001600160a01b0316600c828154811061134e5761134e614074565b6000918252602090912001546001600160a01b031614156113725750600192915050565b8061137c8161408a565b915050611327565b6060600b8054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6002546001600160a01b0316331461140e5760405162461bcd60e51b81526004016108e2906140a5565b600581905560405181815233907f5ee73342e684c0b848562c301fa2dc6b0146b266cfa12d4219fb04b316f7a4759060200160405180910390a250565b6107e9612710670de0b6b3a7640000614194565b600b8181548110610b6057600080fd5b60035460405163226e761560e01b81523360048201526000916001600160a01b03169063226e761590602401602060405180830381865afa1580156114b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114dc9190614210565b6114f85760405162461bcd60e51b81526004016108e29061422b565b61150186611323565b6115605760405162461bcd60e51b815260206004820152602a60248201527f464143544f525920524f555445523a20496e76616c696420466978656450726960448201526918d950dbdb9d1c9858dd60b21b60648201526084016108e2565b60405163012c327560e01b81526001600160a01b0387169063012c3275906115949033908990899089908990600401614276565b6020604051808303816000875af11580156115b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d79190614305565b9695505050505050565b60328111156116025760405162461bcd60e51b81526004016108e29061431e565b60005b818110156119e057600083838381811061162157611621614074565b6116379260206060909202019081019150613cc2565b6001600160a01b0316634df947d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611674573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116989190614360565b90506116c18133308787878181106116b2576116b2614074565b905060600201602001356130f7565b60008484848181106116d5576116d5614074565b6116eb9260206060909202019081019150613cc2565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015611731573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117559190614305565b90506117b785858581811061176c5761176c614074565b6117829260206060909202019081019150613cc2565b86868681811061179457611794614074565b90506060020160200135846001600160a01b03166132459092919063ffffffff16565b60008585858181106117cb576117cb614074565b6117e19260206060909202019081019150613cc2565b6001600160a01b0316638329ab3387878781811061180157611801614074565b9050606002016020013588888881811061181d5761181d614074565b905060600201604001356040518363ffffffff1660e01b815260040161184d929190918252602082015260400190565b6020604051808303816000875af115801561186c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118909190614305565b90508585858181106118a4576118a4614074565b905060600201604001358110156118ed5760405162461bcd60e51b815260206004820152600d60248201526c04e4f5420454e4f554748204c5609c1b60448201526064016108e2565b600086868681811061190157611901614074565b6119179260206060909202019081019150613cc2565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561195d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119819190614305565b90506119c9336119918386613330565b8989898181106119a3576119a3614074565b6119b99260206060909202019081019150613cc2565b6001600160a01b03169190613343565b5050505080806119d89061408a565b915050611605565b505050565b6107e964e8d4a51000670de0b6b3a7640000614194565b6107e9670de0b6b3a76400006064614055565b611a226002670de0b6b3a7640000614194565b6107e990600161437d565b6002546001600160a01b03163314611a575760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116611a7d5760405162461bcd60e51b81526004016108e29061414b565b60005b600c54811015611ad957816001600160a01b0316600c8281548110611aa757611aa7614074565b6000918252602090912001546001600160a01b03161415611ac757611ad9565b80611ad18161408a565b915050611a80565b600c54811015610a5c57600c8054611af39060019061411e565b81548110611b0357611b03614074565b600091825260209091200154600c80546001600160a01b039092169183908110611b2f57611b2f614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600c805480611b6e57611b6e614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917ff1ec0697329a2e8de8cf055335547acc40fbace8712fc77aeea1ea2afbcf7e3b9190a35050565b6002546001600160a01b03163314611bf55760405162461bcd60e51b81526004016108e2906140a5565b610b3681613373565b600c8181548110610b6057600080fd5b6000611c1982610cb4565b15611c2657505060065490565b505060075490565b919050565b6107e9600a670de0b6b3a7640000614194565b6001611c5b670de0b6b3a76400006002614055565b6107e9919061411e565b6002546001600160a01b03163314611c8f5760405162461bcd60e51b81526004016108e2906140a5565b600684905560078390556008829055600981905560408051858152602081018590529081018390526060810182905233907fe6171cf0506862c0a0185f8c21dca979859d4eb63186eff63f1b3dd14926be7b9060800160405180910390a250505050565b6000611cfe82613036565b92915050565b6002546001600160a01b03163314611d2e5760405162461bcd60e51b81526004016108e2906140a5565b610b3681613464565b60035460405163226e761560e01b81523360048201526001600160a01b039091169063226e761590602401602060405180830381865afa158015611d7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da39190614210565b611dbf5760405162461bcd60e51b81526004016108e29061422b565b611dc886612fd5565b611e265760405162461bcd60e51b815260206004820152602960248201527f464143544f525920524f555445523a20496e76616c69642044697370656e73656044820152681c90dbdb9d1c9858dd60ba1b60648201526084016108e2565b6040516324ce291760e01b81526001600160a01b0386811660048301526024820186905260448201859052838116606483015282811660848301528716906324ce29179060a401600060405180830381600087803b158015611e8757600080fd5b505af1158015611e9b573d6000803e3d6000fd5b50505050505050505050565b6002546001600160a01b03163314611ed15760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116611ef75760405162461bcd60e51b81526004016108e2906140d5565b611f0081612fd5565b610b3657600d805460018101825560009182527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b038416908117909155604051909133917f78be9d87a7b2c8707b044dbf5b04c3f747b692c55ec34dcd1d7357736478789c9190a350565b6002546001600160a01b03163314611fa95760405162461bcd60e51b81526004016108e2906140a5565b610b36816134ec565b6002546001600160a01b03163314611fdc5760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b0381166120325760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964206e657720726f75746572206f776e6572000000000000000060448201526064016108e2565b600280546001600160a01b0319166001600160a01b03831690811790915560405133907fc736654a613824c69968e0ec25ac1a428ccd49e15c28e97b5dfd2c6059757e2a90600090a350565b6107e96002670de0b6b3a7640000614194565b60328111156120b25760405162461bcd60e51b81526004016108e29061431e565b60005b818110156119e057600060405180606001604052808585858181106120dc576120dc614074565b9050610140020160600160208101906120f59190613cc2565b6001600160a01b0316815260200185858581811061211557612115614074565b9050610140020160a001602081019061212e9190613cc2565b6001600160a01b0316815260200185858581811061214e5761214e614074565b905061014002016101200160208101906121689190613cc2565b6001600160a01b03166001600160a01b031681525090506000604051806080016040528086868681811061219e5761219e614074565b905061014002016080013581526020018686868181106121c0576121c0614074565b9050610140020160c0013581526020018686868181106121e2576121e2614074565b9050610140020160e00135815260200186868681811061220457612204614074565b90506101400201610100013581525090506000600381111561222857612228614395565b85858581811061223a5761223a614074565b90506101400201604001602081019061225391906143ab565b600381111561226457612264614395565b1415612417576122bc85858581811061227f5761227f614074565b9050610140020160600160208101906122989190613cc2565b33308888888181106122ac576122ac614074565b90506101400201608001356130f7565b6123428585858181106122d1576122d1614074565b9050610140020160200160208101906122ea9190613cc2565b8686868181106122fc576122fc614074565b905061014002016080013587878781811061231957612319614074565b9050610140020160600160208101906123329190613cc2565b6001600160a01b03169190613245565b600085858581811061235657612356614074565b90506101400201602001602081019061236f9190613cc2565b6001600160a01b031663c421a3fc84846040518363ffffffff1660e01b815260040161239c9291906143cc565b60408051808303816000875af11580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190614431565b50905061241133828888888181106123f8576123f8614074565b9050610140020160a00160208101906119b99190613cc2565b50612c1e565b600185858581811061242b5761242b614074565b90506101400201604001602081019061244491906143ab565b600381111561245557612455614395565b141561274757600085858581811061246f5761246f614074565b9050610140020160200160208101906124889190613cc2565b6001600160a01b031663caa011488787878181106124a8576124a8614074565b9050610140020160600160208101906124c19190613cc2565b8888888181106124d3576124d3614074565b9050610140020160a00160208101906124ec9190613cc2565b8989898181106124fe576124fe614074565b9050610140020160c001358a8a8a81811061251b5761251b614074565b6040516001600160e01b031960e089901b1681526001600160a01b039687166004820152959094166024860152506044840191909152610100610140909202010135606482015260840160a060405180830381865afa158015612582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a69190614455565b509293506125e69250889150879050868181106125c5576125c5614074565b9050610140020160600160208101906125de9190613cc2565b3330846130f7565b6126278686868181106125fb576125fb614074565b9050610140020160200160208101906126149190613cc2565b8288888881811061231957612319614074565b600086868681811061263b5761263b614074565b9050610140020160200160208101906126549190613cc2565b6001600160a01b031663c98a59cf85856040518363ffffffff1660e01b81526004016126819291906143cc565b60408051808303816000875af115801561269f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c39190614431565b50835190915081111561270d5760405162461bcd60e51b81526020600482015260126024820152712a27a79026a0a72c902a27a5a2a7299024a760711b60448201526064016108e2565b6127403388888881811061272357612723614074565b9050610140020160c001358989898181106123f8576123f8614074565b5050612c1e565b600285858581811061275b5761275b614074565b90506101400201604001602081019061277491906143ab565b600381111561278557612785614395565b1415612b3557600085858581811061279f5761279f614074565b9050610140020160200160208101906127b89190613cc2565b6001600160a01b0316634c87087d8787878181106127d8576127d8614074565b90506101400201600001356040518263ffffffff1660e01b815260040161280191815260200190565b61018060405180830381865afa15801561281f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128439190614495565b50505050505050505050915050600086868681811061286457612864614074565b90506101400201602001602081019061287d9190613cc2565b6001600160a01b031663dd1bc96a88888881811061289d5761289d614074565b90506101400201600001358989898181106128ba576128ba614074565b9050610140020160c001358a8a8a8181106128d7576128d7614074565b6040516001600160e01b031960e088901b16815260048101959095526024850193909352506101006101409092020101356044820152606401608060405180830381865afa15801561292d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129519190614549565b505050905061296b8787878181106125c5576125c5614074565b6129ac87878781811061298057612980614074565b9050610140020160200160208101906129999190613cc2565b8289898981811061231957612319614074565b8686868181106129be576129be614074565b9050610140020160200160208101906129d79190613cc2565b6001600160a01b03166368c4b7e98888888181106129f7576129f7614074565b9050610140020160000135898989818110612a1457612a14614074565b9050610140020160c001358a8a8a818110612a3157612a31614074565b90506101400201608001358b8b8b818110612a4e57612a4e614074565b90506101400201610120016020810190612a689190613cc2565b8c8c8c818110612a7a57612a7a614074565b6040516001600160e01b031960e08a901b168152600481019790975260248701959095525060448501929092526001600160a01b03166064840152610100610140909202010135608482015260a401600060405180830381600087803b158015612ae357600080fd5b505af1158015612af7573d6000803e3d6000fd5b5050505061274033888888818110612b1157612b11614074565b9050610140020160c00135846001600160a01b03166133439092919063ffffffff16565b848484818110612b4757612b47614074565b905061014002016020016020810190612b609190613cc2565b6001600160a01b0316631d746d83868686818110612b8057612b80614074565b9050610140020160a0016020810190612b999190613cc2565b878787818110612bab57612bab614074565b60405160e086901b6001600160e01b03191681526001600160a01b03949094166004850152610140029190910160c00135602483015250336044820152606401600060405180830381600087803b158015612c0557600080fd5b505af1158015612c19573d6000803e3d6000fd5b505050505b50508080612c2b9061408a565b9150506120b5565b60035460405163226e761560e01b81523360048201526000916001600160a01b03169063226e761590602401602060405180830381865afa158015612c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca09190614210565b612cbc5760405162461bcd60e51b81526004016108e29061422b565b612ce783836000818110612cd257612cd2614074565b905060200201602081019061043f9190613cc2565b612d3e5760405162461bcd60e51b815260206004820152602260248201527f464143544f525920524f555445523a20696e76616c6964207373436f6e74726160448201526118dd60f21b60648201526084016108e2565b600087876001818110612d5357612d53614074565b9050602002013511612d985760405162461bcd60e51b815260206004820152600e60248201526d57726f6e6720646563696d616c7360901b60448201526064016108e2565b612e1a612dab60408a0160208b01613cc2565b84846002818110612dbe57612dbe614074565b9050602002016020810190612dd39190613cc2565b85856000818110612de657612de6614074565b9050602002016020810190612dfb9190613cc2565b8a8a6004818110612e0e57612e0e614074565b905060200201356130f7565b604080518082018252600091612edd91908b90600290839083908082843760009201919091525050604080516020808d0282810182019093528c82529092508c918c9182919085019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020808c0282810182019093528b82529093508b92508a91829185019084908082843760009201919091525061365b92505050565b90506001600160a01b038116612f2d5760405162461bcd60e51b8152602060048201526015602482015274119052531151081513c81111541313d6481413d3d3605a1b60448201526064016108e2565b612f406104f560408b0160208c01613cc2565b15612f8957604051600181526001600160a01b038216907f90279d7790471e260411db76079630dfaa838fc987d29ae7aa7dc1bcd773ef2e9060200160405180910390a2612fc9565b604051600081526001600160a01b038216907f90279d7790471e260411db76079630dfaa838fc987d29ae7aa7dc1bcd773ef2e9060200160405180910390a25b98975050505050505050565b6000805b600d5481101561084d57826001600160a01b0316600d828154811061300057613000614074565b6000918252602090912001546001600160a01b031614156130245750600192915050565b8061302e8161408a565b915050612fd9565b6000805b60015481101561084d57826001600160a01b03166001828154811061306157613061614074565b6000918252602090912001546001600160a01b031614156130855750600192915050565b8061308f8161408a565b91505061303a565b606060018054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908616906370a0823190602401602060405180830381865afa158015613141573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131659190614305565b905061317c6001600160a01b03861685858561398f565b61318681836139c7565b6040516370a0823160e01b81526001600160a01b0385811660048301528716906370a0823190602401602060405180830381865afa1580156131cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f09190614305565b101561323e5760405162461bcd60e51b815260206004820152601a60248201527f5472616e7366657220616d6f756e7420697320746f6f206c6f7700000000000060448201526064016108e2565b5050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015613296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ba9190614305565b6132c4919061437d565b6040516001600160a01b03851660248201526044810182905290915061332a90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526139d3565b50505050565b600061333c828461411e565b9392505050565b6040516001600160a01b0383166024820152604481018290526119e090849063a9059cbb60e01b906064016132f3565b6001600160a01b0381166133dd5760405162461bcd60e51b815260206004820152602b60248201527f466163746f7279526f757465723a20496e76616c696420706f6f6c54656d706c60448201526a617465206164647265737360a81b60648201526084016108e2565b6133e681611cf3565b610b365760018054808201825560009182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b038416908117909155604051909133917fc3674c32cbec94fe266aab7ef71f65b9bf77e1ed501d4f2bece8752f5352e9ac9190a350565b61346d81610cb4565b610b3657600a805460018101825560009182527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b0319166001600160a01b038416908117909155604051909133917fdffbd9ded1c09446f09377de547142dcce7dc541c8b0b028142b1eba7026b9e79190a350565b60005b60015481101561354857816001600160a01b03166001828154811061351657613516614074565b6000918252602090912001546001600160a01b0316141561353657613548565b806135408161408a565b9150506134ef565b600154811015610a5c57805b60018054613562919061411e565b8110156135ec576001613575828261437d565b8154811061358557613585614074565b600091825260209091200154600180546001600160a01b0390921691839081106135b1576135b1614074565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055806135e48161408a565b915050613554565b5060018054806135fe576135fe614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917fc73fd5d40669565e257cbcd153784617ef26acfcc9fead31e68c0dce3ce82fb29190a35050565b60006136808260058151811061367357613673614074565b6020026020010151611cf3565b6136cc5760405162461bcd60e51b815260206004820152601d60248201527f42466163746f72793a2057726f6e6720506f6f6c2054656d706c61746500000060448201526064016108e2565b60006040518060200160405280846004815181106136ec576136ec614074565b60200260200101516001600160a01b03166001600160a01b0316815250905061372e8360058151811061372157613721614074565b6020026020010151613aa5565b91506001600160a01b0382166137925760405162461bcd60e51b8152602060048201526024808201527f42466163746f72793a20696e76616c69642062706f6f6c207a65726f206164646044820152637265737360e01b60648201526084016108e2565b6000829050806001600160a01b031663284e97a9856000815181106137b9576137b9614074565b602002602001015130886000808d896040518863ffffffff1660e01b81526004016137ea97969594939291906145e6565b6020604051808303816000875af1158015613809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061382d9190614210565b6138705760405162461bcd60e51b815260206004820152601460248201527311549497d253925512505312569157d09413d3d360621b60448201526064016108e2565b8360008151811061388357613883614074565b60200260200101516001600160a01b03166383b87e5a886000600281106138ac576138ac614074565b6020020151896001602002015186886003815181106138cd576138cd614074565b60200260200101518b6040518663ffffffff1660e01b81526004016138f695949392919061465f565b6020604051808303816000875af1158015613915573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139399190614210565b6139855760405162461bcd60e51b815260206004820152601a60248201527f4552525f494e495449414c495a455f534944455354414b494e4700000000000060448201526064016108e2565b5050949350505050565b6040516001600160a01b038085166024830152831660448201526064810182905261332a9085906323b872dd60e01b906084016132f3565b600061333c828461437d565b6000613a28826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613b359092919063ffffffff16565b8051909150156119e05780806020019051810190613a469190614210565b6119e05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108e2565b6000808260601b9050604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528160148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f06040516001600160a01b03821681529093507f117c72e6c25f0a072e36e148df71468ce2f3dbe7defec5b2c257a6e3eb65278c915060200160405180910390a150919050565b6060613b448484600085613b4c565b949350505050565b606082471015613bad5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016108e2565b843b613bfb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108e2565b600080866001600160a01b03168587604051613c1791906146c7565b60006040518083038185875af1925050503d8060008114613c54576040519150601f19603f3d011682016040523d82523d6000602084013e613c59565b606091505b5091509150613c69828286613c74565b979650505050505050565b60608315613c8357508161333c565b825115613c935782518084602001fd5b8160405162461bcd60e51b81526004016108e291906146e3565b6001600160a01b0381168114610b3657600080fd5b600060208284031215613cd457600080fd5b813561333c81613cad565b6020808252825182820181905260009190848201906040850190845b81811015613d205783516001600160a01b031683529284019291840191600101613cfb565b50909695505050505050565b600060208284031215613d3e57600080fd5b5035919050565b60008083601f840112613d5757600080fd5b50813567ffffffffffffffff811115613d6f57600080fd5b6020830191508360208260051b8501011115613d8a57600080fd5b9250929050565b600080600080600060608688031215613da957600080fd5b8535613db481613cad565b9450602086013567ffffffffffffffff80821115613dd157600080fd5b613ddd89838a01613d45565b90965094506040880135915080821115613df657600080fd5b50613e0388828901613d45565b969995985093965092949392505050565b60008060208385031215613e2757600080fd5b823567ffffffffffffffff80821115613e3f57600080fd5b818501915085601f830112613e5357600080fd5b813581811115613e6257600080fd5b866020606083028501011115613e7757600080fd5b60209290920196919550909350505050565b60008060008060808587031215613e9f57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060008060c08789031215613ed457600080fd5b8635613edf81613cad565b95506020870135613eef81613cad565b945060408701359350606087013592506080870135613f0d81613cad565b915060a0870135613f1d81613cad565b809150509295509295509295565b60008060208385031215613f3e57600080fd5b823567ffffffffffffffff80821115613f5657600080fd5b818501915085601f830112613f6a57600080fd5b813581811115613f7957600080fd5b86602061014083028501011115613e7757600080fd5b600080600080600080600060a0888a031215613faa57600080fd5b6040880189811115613fbb57600080fd5b8897503567ffffffffffffffff80821115613fd557600080fd5b613fe18b838c01613d45565b909850965060608a0135915080821115613ffa57600080fd5b6140068b838c01613d45565b909650945060808a013591508082111561401f57600080fd5b5061402c8a828b01613d45565b989b979a50959850939692959293505050565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561406f5761406f61403f565b500290565b634e487b7160e01b600052603260045260246000fd5b600060001982141561409e5761409e61403f565b5060010190565b60208082526016908201527527b1b2b0b72937baba32b91d102727aa1027aba722a960511b604082015260600190565b60208082526029908201527f466163746f7279526f757465723a20496e76616c6964205f64697370656e736560408201526872206164647265737360b81b606082015260800190565b6000828210156141305761413061403f565b500390565b634e487b7160e01b600052603160045260246000fd5b60208082526029908201527f466163746f7279526f757465723a20496e76616c6964205f666978656452617460408201526865206164647265737360b81b606082015260800190565b6000826141b157634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602a908201527f466163746f7279526f757465723a20496e76616c6964205f7373436f6e7472616040820152696374206164647265737360b01b606082015260800190565b80518015158114611c2e57600080fd5b60006020828403121561422257600080fd5b61333c82614200565b6020808252602b908201527f464143544f525920524f555445523a204e4f54204f524947494e414c2045524360408201526a32302054454d504c41544560a81b606082015260800190565b6001600160a01b03868116825260606020808401829052908301869052600091879160808501845b898110156142c55784356142b181613cad565b84168252938201939082019060010161429e565b5085810360408701528681526001600160fb1b038711156142e557600080fd5b8660051b9350838883830137600093010191825250979650505050505050565b60006020828403121561431757600080fd5b5051919050565b60208082526022908201527f466163746f7279526f757465723a20546f6f204d616e79204f7065726174696f6040820152616e7360f01b606082015260800190565b60006020828403121561437257600080fd5b815161333c81613cad565b600082198211156143905761439061403f565b500190565b634e487b7160e01b600052602160045260246000fd5b6000602082840312156143bd57600080fd5b81356004811061333c57600080fd5b60e08101818460005b60038110156143fd5781516001600160a01b03168352602092830192909101906001016143d5565b505050606082018360005b6004811015614427578151835260209283019290910190600101614408565b5050509392505050565b6000806040838503121561444457600080fd5b505080516020909101519092909150565b600080600080600060a0868803121561446d57600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6000806000806000806000806000806000806101808d8f0312156144b857600080fd5b8c516144c381613cad565b60208e0151909c506144d481613cad565b60408e015160608f0151919c509a506144ec81613cad565b60808e015160a08f0151919a509850965061450960c08e01614200565b955060e08d015194506101008d015193506101208d015192506101408d015191506145376101608e01614200565b90509295989b509295989b509295989b565b6000806000806080858703121561455f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b600081518084526020808501945080840160005b838110156145af57815187529582019590820190600101614593565b509495945050505050565b8060005b600181101561332a5781516001600160a01b03168452602093840193909101906001016145be565b600061010060018060a01b03808b1684526020818b16818601528260408601526146128386018b61457f565b93508815156060860152871515608086015260a0850192508660005b600281101561464d57815184168552938201939082019060010161462e565b5050505050612fc960e08301846145ba565b6001600160a01b038681168252858116602083015284811660408301528316606082015260a060808201819052600090613c699083018461457f565b60005b838110156146b657818101518382015260200161469e565b8381111561332a5750506000910152565b600082516146d981846020870161469b565b9190910192915050565b602081526000825180602084015261470281604085016020870161469b565b601f01601f1916919091016040019291505056fea2646970667358221220c67e8fca36a392ffc78255f877c99882c98a625746868858035b2cf86a93d1ba64736f6c634300080c0033000000000000000000000000c7ec1970b09224b317c52d92f37f5e1e4ff6b687000000000000000000000000967da4048cd07ab37855c090aaf366e4ce1b9f480000000000000000000000008dac419d5d81af8c8e795d0d73f64d5220e28cd800000000000000000000000049e35cd2bae043abd9074b6e5a649a5adeb05c3300000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103e65760003560e01c8063858ab5961161020a578063c45a015511610125578063e183fb3f116100b8578063e525f99c11610087578063e525f99c14610782578063ec09302114610795578063ecdda5881461079d578063ee3bc635146107b0578063fca24bc6146107c357600080fd5b8063e183fb3f1461075d578063e193faad14610766578063e2bdeefa14610779578063e4a28a521461041b57600080fd5b8063cd10534b116100f4578063cd10534b14610709578063d629a00a1461071c578063dce2d0df1461072f578063de9a95a71461074a57600080fd5b8063c45a0155146106dc578063c6580d12146106ef578063c6e983d9146106f7578063cb870cbf1461070057600080fd5b8063b7b800a41161019d578063bc694ea21161016c578063bc694ea2146106ae578063bfa04b85146106b6578063c07c00fe146106c9578063c36596a6146104bd57600080fd5b8063b7b800a41461065d578063b8421e2b1461068b578063ba019dab1461069e578063bc063e1a146106a657600080fd5b80639f2c010a116101d95780639f2c010a1461064a578063b0e0d1361461065d578063b19aaac614610665578063b66806fb1461067857600080fd5b8063858ab5961461061f578063867378c5146106325780639381cd2b1461063a578063992e2a921461064257600080fd5b8063475030c0116103055780636cdf90a1116102985780637cbf85bf116102675780637cbf85bf146105cb5780637d28354d146105de578063802d1422146105e657806382449375146105f95780638552730a1461060c57600080fd5b80636cdf90a114610595578063737e5ca0146105a85780637521aff9146105b057806376c7a3c7146105c357600080fd5b80635705987a116102d45780635705987a1461055f5780636afc0c5f146105725780636c45e8811461057a5780636c9fb6121461058257600080fd5b8063475030c01461052857806347e140941461053157806350cbbe7614610544578063510f34651461055757600080fd5b80631dafede01161037d5780632d5ad3d51161034c5780632d5ad3d5146104e7578063335b7fa2146104fa578063415792081461050d57806346104ea81461052057600080fd5b80631dafede0146104aa578063218b5382146104bd578063241c7a6d146104cc57806329ce1ec5146104d457600080fd5b806316592614116103b9578063165926141461046957806316d9cb3d1461047e578063189d00ca146104915780631a81876d1461049957600080fd5b806303814238146103eb57806309a3bbe41461041b57806315c25dd51461043157806315d4c9eb14610454575b600080fd5b6000546103fe906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6104236107d6565b604051908152602001610412565b61044461043f366004613cc2565b6107ec565b6040519015158152602001610412565b61045c610856565b6040516104129190613cdf565b61047c610477366004613cc2565b6108b8565b005b61047c61048c366004613cc2565b610a60565b610423610b39565b6000546001600160a01b03166103fe565b6103fe6104b8366004613d2c565b610b50565b610423670de0b6b3a764000081565b61045c610b7a565b61047c6104e2366004613cc2565b610b89565b6104446104f5366004613cc2565b610cb4565b6103fe610508366004613d2c565b610d15565b61047c61051b366004613cc2565b610d25565b61045c610dfc565b61042360055481565b61047c61053f366004613cc2565b610e5c565b6103fe610552366004613d2c565b610ffa565b600554610423565b61047c61056d366004613cc2565b61100a565b61045c6111eb565b600954610423565b61047c610590366004613cc2565b61124b565b6104446105a3366004613cc2565b611323565b61045c611384565b61047c6105be366004613d2c565b6113e4565b61042361144b565b6103fe6105d9366004613d2c565b61145f565b600854610423565b6004546103fe906001600160a01b031681565b610423610607366004613d91565b61146f565b6002546103fe906001600160a01b031681565b61047c61062d366004613e14565b6115e1565b6104236119e5565b6104236119fc565b610423611a0f565b61047c610658366004613cc2565b611a2d565b610423600281565b61047c610673366004613cc2565b611bcb565b6103fe610686366004613d2c565b611bfe565b610423610699366004613cc2565b611c0e565b610423600181565b610423611c33565b610423611c46565b61047c6106c4366004613e89565b611c65565b6104446106d7366004613cc2565b611cf3565b6003546103fe906001600160a01b031681565b610423600081565b61042360095481565b61042360075481565b61047c610717366004613cc2565b611d04565b61047c61072a366004613ebb565b611d37565b60065460075460408051928352602083019190915201610412565b61047c610758366004613cc2565b611ea7565b61042360065481565b61047c610774366004613cc2565b611f7f565b61042360085481565b61047c610790366004613cc2565b611fb2565b61042361207e565b61047c6107ab366004613f2b565b612091565b6103fe6107be366004613f8f565b612c33565b6104446107d1366004613cc2565b612fd5565b6107e9670de0b6b3a76400006032614055565b81565b6000805b600b5481101561084d57826001600160a01b0316600b828154811061081757610817614074565b6000918252602090912001546001600160a01b0316141561083b5750600192915050565b806108458161408a565b9150506107f0565b50600092915050565b6060600d8054806020026020016040519081016040528092919081815260200182805480156108ae57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610890575b5050505050905090565b6002546001600160a01b031633146108eb5760405162461bcd60e51b81526004016108e2906140a5565b60405180910390fd5b6001600160a01b0381166109115760405162461bcd60e51b81526004016108e2906140d5565b60005b600d5481101561096d57816001600160a01b0316600d828154811061093b5761093b614074565b6000918252602090912001546001600160a01b0316141561095b5761096d565b806109658161408a565b915050610914565b600d54811015610a5c57600d80546109879060019061411e565b8154811061099757610997614074565b600091825260209091200154600d80546001600160a01b0390921691839081106109c3576109c3614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600d805480610a0257610a02614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917f63fe522dcdc5f006279afe8840a87398bb3d0dbb906b848866195859621908b39190a35b5050565b6002546001600160a01b03163314610a8a5760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610ab05760405162461bcd60e51b81526004016108e29061414b565b610ab981611323565b610b3657600c805460018101825560009182527fdf6966c971051c3d54ec59162606531493a51404a002842f56009d7e5cf4a8c70180546001600160a01b0319166001600160a01b038416908117909155604051909133917f45ccb9b9d6b112eb7a38daf6a23bda8b4c8449d5cf64a034975a5beb8cdd37b39190a35b50565b6107e96402540be400670de0b6b3a7640000614194565b600a8181548110610b6057600080fd5b6000918252602090912001546001600160a01b0316905081565b6060610b84613097565b905090565b6002546001600160a01b03163314610bb35760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610c195760405162461bcd60e51b815260206004820152602760248201527f466163746f7279526f757465723a20496e76616c6964205f666163746f7279206044820152666164647265737360c81b60648201526084016108e2565b6003546001600160a01b031615610c685760405162461bcd60e51b8152602060048201526013602482015272119050d513d49648105314915051164814d155606a1b60448201526064016108e2565b600380546001600160a01b0319166001600160a01b03831690811790915560405133907f1f869f1ddaa0e2e3652252b3394c05c805f54a0d5f7fb6975f785ae4f91e587190600090a350565b6000805b600a5481101561084d57826001600160a01b0316600a8281548110610cdf57610cdf614074565b6000918252602090912001546001600160a01b03161415610d035750600192915050565b80610d0d8161408a565b915050610cb8565b600d8181548110610b6057600080fd5b6002546001600160a01b03163314610d4f5760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610db15760405162461bcd60e51b8152602060048201526024808201527f4e6577206f7063436f6c6c6563746f722063616e6e6f74206265205a45524f5f60448201526320a2222960e11b60648201526084016108e2565b600080546001600160a01b0319166001600160a01b0383169081178255604051909133917fbadc0056fc46a437b2d0a4e9ae17a4f964e18972b5f2455b98b7331c1401a80f9190a350565b6060600c8054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6002546001600160a01b03163314610e865760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116610eac5760405162461bcd60e51b81526004016108e2906141b6565b60005b600b54811015610f0857816001600160a01b0316600b8281548110610ed657610ed6614074565b6000918252602090912001546001600160a01b03161415610ef657610f08565b80610f008161408a565b915050610eaf565b600b54811015610a5c57600b8054610f229060019061411e565b81548110610f3257610f32614074565b600091825260209091200154600b80546001600160a01b039092169183908110610f5e57610f5e614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600b805480610f9d57610f9d614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917f7df5d17d768be6563796784637c80bc9204e2af0bc4ba8630f5aa2fed96ea4879190a35050565b60018181548110610b6057600080fd5b6002546001600160a01b031633146110345760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b03811661109d5760405162461bcd60e51b815260206004820152602a60248201527f466163746f7279526f757465723a20496e76616c6964204f6365616e20546f6b604482015269656e206164647265737360b01b60648201526084016108e2565b60005b600a548110156110f957816001600160a01b0316600a82815481106110c7576110c7614074565b6000918252602090912001546001600160a01b031614156110e7576110f9565b806110f18161408a565b9150506110a0565b600a54811015610a5c57600a80546111139060019061411e565b8154811061112357611123614074565b600091825260209091200154600a80546001600160a01b03909216918390811061114f5761114f614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600a80548061118e5761118e614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917fbbe55b1ff108e23e5ff1a6f5d36946eec15ec0ca0ded2bfed4cdcf697ca904609190a35050565b6060600a8054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6002546001600160a01b031633146112755760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b03811661129b5760405162461bcd60e51b81526004016108e2906141b6565b6112a4816107ec565b610b3657600b805460018101825560009182527f0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90180546001600160a01b0319166001600160a01b038416908117909155604051909133917fcef3ce01f85c030161b431114e41e463297b68f169c1013c526b1cbc5747e5449190a350565b6000805b600c5481101561084d57826001600160a01b0316600c828154811061134e5761134e614074565b6000918252602090912001546001600160a01b031614156113725750600192915050565b8061137c8161408a565b915050611327565b6060600b8054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6002546001600160a01b0316331461140e5760405162461bcd60e51b81526004016108e2906140a5565b600581905560405181815233907f5ee73342e684c0b848562c301fa2dc6b0146b266cfa12d4219fb04b316f7a4759060200160405180910390a250565b6107e9612710670de0b6b3a7640000614194565b600b8181548110610b6057600080fd5b60035460405163226e761560e01b81523360048201526000916001600160a01b03169063226e761590602401602060405180830381865afa1580156114b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114dc9190614210565b6114f85760405162461bcd60e51b81526004016108e29061422b565b61150186611323565b6115605760405162461bcd60e51b815260206004820152602a60248201527f464143544f525920524f555445523a20496e76616c696420466978656450726960448201526918d950dbdb9d1c9858dd60b21b60648201526084016108e2565b60405163012c327560e01b81526001600160a01b0387169063012c3275906115949033908990899089908990600401614276565b6020604051808303816000875af11580156115b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d79190614305565b9695505050505050565b60328111156116025760405162461bcd60e51b81526004016108e29061431e565b60005b818110156119e057600083838381811061162157611621614074565b6116379260206060909202019081019150613cc2565b6001600160a01b0316634df947d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611674573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116989190614360565b90506116c18133308787878181106116b2576116b2614074565b905060600201602001356130f7565b60008484848181106116d5576116d5614074565b6116eb9260206060909202019081019150613cc2565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa158015611731573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117559190614305565b90506117b785858581811061176c5761176c614074565b6117829260206060909202019081019150613cc2565b86868681811061179457611794614074565b90506060020160200135846001600160a01b03166132459092919063ffffffff16565b60008585858181106117cb576117cb614074565b6117e19260206060909202019081019150613cc2565b6001600160a01b0316638329ab3387878781811061180157611801614074565b9050606002016020013588888881811061181d5761181d614074565b905060600201604001356040518363ffffffff1660e01b815260040161184d929190918252602082015260400190565b6020604051808303816000875af115801561186c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118909190614305565b90508585858181106118a4576118a4614074565b905060600201604001358110156118ed5760405162461bcd60e51b815260206004820152600d60248201526c04e4f5420454e4f554748204c5609c1b60448201526064016108e2565b600086868681811061190157611901614074565b6119179260206060909202019081019150613cc2565b6040516370a0823160e01b81523060048201526001600160a01b0391909116906370a0823190602401602060405180830381865afa15801561195d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119819190614305565b90506119c9336119918386613330565b8989898181106119a3576119a3614074565b6119b99260206060909202019081019150613cc2565b6001600160a01b03169190613343565b5050505080806119d89061408a565b915050611605565b505050565b6107e964e8d4a51000670de0b6b3a7640000614194565b6107e9670de0b6b3a76400006064614055565b611a226002670de0b6b3a7640000614194565b6107e990600161437d565b6002546001600160a01b03163314611a575760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116611a7d5760405162461bcd60e51b81526004016108e29061414b565b60005b600c54811015611ad957816001600160a01b0316600c8281548110611aa757611aa7614074565b6000918252602090912001546001600160a01b03161415611ac757611ad9565b80611ad18161408a565b915050611a80565b600c54811015610a5c57600c8054611af39060019061411e565b81548110611b0357611b03614074565b600091825260209091200154600c80546001600160a01b039092169183908110611b2f57611b2f614074565b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600c805480611b6e57611b6e614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917ff1ec0697329a2e8de8cf055335547acc40fbace8712fc77aeea1ea2afbcf7e3b9190a35050565b6002546001600160a01b03163314611bf55760405162461bcd60e51b81526004016108e2906140a5565b610b3681613373565b600c8181548110610b6057600080fd5b6000611c1982610cb4565b15611c2657505060065490565b505060075490565b919050565b6107e9600a670de0b6b3a7640000614194565b6001611c5b670de0b6b3a76400006002614055565b6107e9919061411e565b6002546001600160a01b03163314611c8f5760405162461bcd60e51b81526004016108e2906140a5565b600684905560078390556008829055600981905560408051858152602081018590529081018390526060810182905233907fe6171cf0506862c0a0185f8c21dca979859d4eb63186eff63f1b3dd14926be7b9060800160405180910390a250505050565b6000611cfe82613036565b92915050565b6002546001600160a01b03163314611d2e5760405162461bcd60e51b81526004016108e2906140a5565b610b3681613464565b60035460405163226e761560e01b81523360048201526001600160a01b039091169063226e761590602401602060405180830381865afa158015611d7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611da39190614210565b611dbf5760405162461bcd60e51b81526004016108e29061422b565b611dc886612fd5565b611e265760405162461bcd60e51b815260206004820152602960248201527f464143544f525920524f555445523a20496e76616c69642044697370656e73656044820152681c90dbdb9d1c9858dd60ba1b60648201526084016108e2565b6040516324ce291760e01b81526001600160a01b0386811660048301526024820186905260448201859052838116606483015282811660848301528716906324ce29179060a401600060405180830381600087803b158015611e8757600080fd5b505af1158015611e9b573d6000803e3d6000fd5b50505050505050505050565b6002546001600160a01b03163314611ed15760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b038116611ef75760405162461bcd60e51b81526004016108e2906140d5565b611f0081612fd5565b610b3657600d805460018101825560009182527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b038416908117909155604051909133917f78be9d87a7b2c8707b044dbf5b04c3f747b692c55ec34dcd1d7357736478789c9190a350565b6002546001600160a01b03163314611fa95760405162461bcd60e51b81526004016108e2906140a5565b610b36816134ec565b6002546001600160a01b03163314611fdc5760405162461bcd60e51b81526004016108e2906140a5565b6001600160a01b0381166120325760405162461bcd60e51b815260206004820152601860248201527f496e76616c6964206e657720726f75746572206f776e6572000000000000000060448201526064016108e2565b600280546001600160a01b0319166001600160a01b03831690811790915560405133907fc736654a613824c69968e0ec25ac1a428ccd49e15c28e97b5dfd2c6059757e2a90600090a350565b6107e96002670de0b6b3a7640000614194565b60328111156120b25760405162461bcd60e51b81526004016108e29061431e565b60005b818110156119e057600060405180606001604052808585858181106120dc576120dc614074565b9050610140020160600160208101906120f59190613cc2565b6001600160a01b0316815260200185858581811061211557612115614074565b9050610140020160a001602081019061212e9190613cc2565b6001600160a01b0316815260200185858581811061214e5761214e614074565b905061014002016101200160208101906121689190613cc2565b6001600160a01b03166001600160a01b031681525090506000604051806080016040528086868681811061219e5761219e614074565b905061014002016080013581526020018686868181106121c0576121c0614074565b9050610140020160c0013581526020018686868181106121e2576121e2614074565b9050610140020160e00135815260200186868681811061220457612204614074565b90506101400201610100013581525090506000600381111561222857612228614395565b85858581811061223a5761223a614074565b90506101400201604001602081019061225391906143ab565b600381111561226457612264614395565b1415612417576122bc85858581811061227f5761227f614074565b9050610140020160600160208101906122989190613cc2565b33308888888181106122ac576122ac614074565b90506101400201608001356130f7565b6123428585858181106122d1576122d1614074565b9050610140020160200160208101906122ea9190613cc2565b8686868181106122fc576122fc614074565b905061014002016080013587878781811061231957612319614074565b9050610140020160600160208101906123329190613cc2565b6001600160a01b03169190613245565b600085858581811061235657612356614074565b90506101400201602001602081019061236f9190613cc2565b6001600160a01b031663c421a3fc84846040518363ffffffff1660e01b815260040161239c9291906143cc565b60408051808303816000875af11580156123ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123de9190614431565b50905061241133828888888181106123f8576123f8614074565b9050610140020160a00160208101906119b99190613cc2565b50612c1e565b600185858581811061242b5761242b614074565b90506101400201604001602081019061244491906143ab565b600381111561245557612455614395565b141561274757600085858581811061246f5761246f614074565b9050610140020160200160208101906124889190613cc2565b6001600160a01b031663caa011488787878181106124a8576124a8614074565b9050610140020160600160208101906124c19190613cc2565b8888888181106124d3576124d3614074565b9050610140020160a00160208101906124ec9190613cc2565b8989898181106124fe576124fe614074565b9050610140020160c001358a8a8a81811061251b5761251b614074565b6040516001600160e01b031960e089901b1681526001600160a01b039687166004820152959094166024860152506044840191909152610100610140909202010135606482015260840160a060405180830381865afa158015612582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125a69190614455565b509293506125e69250889150879050868181106125c5576125c5614074565b9050610140020160600160208101906125de9190613cc2565b3330846130f7565b6126278686868181106125fb576125fb614074565b9050610140020160200160208101906126149190613cc2565b8288888881811061231957612319614074565b600086868681811061263b5761263b614074565b9050610140020160200160208101906126549190613cc2565b6001600160a01b031663c98a59cf85856040518363ffffffff1660e01b81526004016126819291906143cc565b60408051808303816000875af115801561269f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c39190614431565b50835190915081111561270d5760405162461bcd60e51b81526020600482015260126024820152712a27a79026a0a72c902a27a5a2a7299024a760711b60448201526064016108e2565b6127403388888881811061272357612723614074565b9050610140020160c001358989898181106123f8576123f8614074565b5050612c1e565b600285858581811061275b5761275b614074565b90506101400201604001602081019061277491906143ab565b600381111561278557612785614395565b1415612b3557600085858581811061279f5761279f614074565b9050610140020160200160208101906127b89190613cc2565b6001600160a01b0316634c87087d8787878181106127d8576127d8614074565b90506101400201600001356040518263ffffffff1660e01b815260040161280191815260200190565b61018060405180830381865afa15801561281f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128439190614495565b50505050505050505050915050600086868681811061286457612864614074565b90506101400201602001602081019061287d9190613cc2565b6001600160a01b031663dd1bc96a88888881811061289d5761289d614074565b90506101400201600001358989898181106128ba576128ba614074565b9050610140020160c001358a8a8a8181106128d7576128d7614074565b6040516001600160e01b031960e088901b16815260048101959095526024850193909352506101006101409092020101356044820152606401608060405180830381865afa15801561292d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129519190614549565b505050905061296b8787878181106125c5576125c5614074565b6129ac87878781811061298057612980614074565b9050610140020160200160208101906129999190613cc2565b8289898981811061231957612319614074565b8686868181106129be576129be614074565b9050610140020160200160208101906129d79190613cc2565b6001600160a01b03166368c4b7e98888888181106129f7576129f7614074565b9050610140020160000135898989818110612a1457612a14614074565b9050610140020160c001358a8a8a818110612a3157612a31614074565b90506101400201608001358b8b8b818110612a4e57612a4e614074565b90506101400201610120016020810190612a689190613cc2565b8c8c8c818110612a7a57612a7a614074565b6040516001600160e01b031960e08a901b168152600481019790975260248701959095525060448501929092526001600160a01b03166064840152610100610140909202010135608482015260a401600060405180830381600087803b158015612ae357600080fd5b505af1158015612af7573d6000803e3d6000fd5b5050505061274033888888818110612b1157612b11614074565b9050610140020160c00135846001600160a01b03166133439092919063ffffffff16565b848484818110612b4757612b47614074565b905061014002016020016020810190612b609190613cc2565b6001600160a01b0316631d746d83868686818110612b8057612b80614074565b9050610140020160a0016020810190612b999190613cc2565b878787818110612bab57612bab614074565b60405160e086901b6001600160e01b03191681526001600160a01b03949094166004850152610140029190910160c00135602483015250336044820152606401600060405180830381600087803b158015612c0557600080fd5b505af1158015612c19573d6000803e3d6000fd5b505050505b50508080612c2b9061408a565b9150506120b5565b60035460405163226e761560e01b81523360048201526000916001600160a01b03169063226e761590602401602060405180830381865afa158015612c7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ca09190614210565b612cbc5760405162461bcd60e51b81526004016108e29061422b565b612ce783836000818110612cd257612cd2614074565b905060200201602081019061043f9190613cc2565b612d3e5760405162461bcd60e51b815260206004820152602260248201527f464143544f525920524f555445523a20696e76616c6964207373436f6e74726160448201526118dd60f21b60648201526084016108e2565b600087876001818110612d5357612d53614074565b9050602002013511612d985760405162461bcd60e51b815260206004820152600e60248201526d57726f6e6720646563696d616c7360901b60448201526064016108e2565b612e1a612dab60408a0160208b01613cc2565b84846002818110612dbe57612dbe614074565b9050602002016020810190612dd39190613cc2565b85856000818110612de657612de6614074565b9050602002016020810190612dfb9190613cc2565b8a8a6004818110612e0e57612e0e614074565b905060200201356130f7565b604080518082018252600091612edd91908b90600290839083908082843760009201919091525050604080516020808d0282810182019093528c82529092508c918c9182919085019084908082843760009201919091525050604080516020808d0282810182019093528c82529093508c92508b91829185019084908082843760009201919091525050604080516020808c0282810182019093528b82529093508b92508a91829185019084908082843760009201919091525061365b92505050565b90506001600160a01b038116612f2d5760405162461bcd60e51b8152602060048201526015602482015274119052531151081513c81111541313d6481413d3d3605a1b60448201526064016108e2565b612f406104f560408b0160208c01613cc2565b15612f8957604051600181526001600160a01b038216907f90279d7790471e260411db76079630dfaa838fc987d29ae7aa7dc1bcd773ef2e9060200160405180910390a2612fc9565b604051600081526001600160a01b038216907f90279d7790471e260411db76079630dfaa838fc987d29ae7aa7dc1bcd773ef2e9060200160405180910390a25b98975050505050505050565b6000805b600d5481101561084d57826001600160a01b0316600d828154811061300057613000614074565b6000918252602090912001546001600160a01b031614156130245750600192915050565b8061302e8161408a565b915050612fd9565b6000805b60015481101561084d57826001600160a01b03166001828154811061306157613061614074565b6000918252602090912001546001600160a01b031614156130855750600192915050565b8061308f8161408a565b91505061303a565b606060018054806020026020016040519081016040528092919081815260200182805480156108ae576020028201919060005260206000209081546001600160a01b03168152600190910190602001808311610890575050505050905090565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908616906370a0823190602401602060405180830381865afa158015613141573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131659190614305565b905061317c6001600160a01b03861685858561398f565b61318681836139c7565b6040516370a0823160e01b81526001600160a01b0385811660048301528716906370a0823190602401602060405180830381865afa1580156131cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131f09190614305565b101561323e5760405162461bcd60e51b815260206004820152601a60248201527f5472616e7366657220616d6f756e7420697320746f6f206c6f7700000000000060448201526064016108e2565b5050505050565b604051636eb1769f60e11b81523060048201526001600160a01b038381166024830152600091839186169063dd62ed3e90604401602060405180830381865afa158015613296573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ba9190614305565b6132c4919061437d565b6040516001600160a01b03851660248201526044810182905290915061332a90859063095ea7b360e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526139d3565b50505050565b600061333c828461411e565b9392505050565b6040516001600160a01b0383166024820152604481018290526119e090849063a9059cbb60e01b906064016132f3565b6001600160a01b0381166133dd5760405162461bcd60e51b815260206004820152602b60248201527f466163746f7279526f757465723a20496e76616c696420706f6f6c54656d706c60448201526a617465206164647265737360a81b60648201526084016108e2565b6133e681611cf3565b610b365760018054808201825560009182527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b038416908117909155604051909133917fc3674c32cbec94fe266aab7ef71f65b9bf77e1ed501d4f2bece8752f5352e9ac9190a350565b61346d81610cb4565b610b3657600a805460018101825560009182527fc65a7bb8d6351c1cf70c95a316cc6a92839c986682d98bc35f958f4883f9d2a80180546001600160a01b0319166001600160a01b038416908117909155604051909133917fdffbd9ded1c09446f09377de547142dcce7dc541c8b0b028142b1eba7026b9e79190a350565b60005b60015481101561354857816001600160a01b03166001828154811061351657613516614074565b6000918252602090912001546001600160a01b0316141561353657613548565b806135408161408a565b9150506134ef565b600154811015610a5c57805b60018054613562919061411e565b8110156135ec576001613575828261437d565b8154811061358557613585614074565b600091825260209091200154600180546001600160a01b0390921691839081106135b1576135b1614074565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055806135e48161408a565b915050613554565b5060018054806135fe576135fe614135565b600082815260208120820160001990810180546001600160a01b03191690559091019091556040516001600160a01b0384169133917fc73fd5d40669565e257cbcd153784617ef26acfcc9fead31e68c0dce3ce82fb29190a35050565b60006136808260058151811061367357613673614074565b6020026020010151611cf3565b6136cc5760405162461bcd60e51b815260206004820152601d60248201527f42466163746f72793a2057726f6e6720506f6f6c2054656d706c61746500000060448201526064016108e2565b60006040518060200160405280846004815181106136ec576136ec614074565b60200260200101516001600160a01b03166001600160a01b0316815250905061372e8360058151811061372157613721614074565b6020026020010151613aa5565b91506001600160a01b0382166137925760405162461bcd60e51b8152602060048201526024808201527f42466163746f72793a20696e76616c69642062706f6f6c207a65726f206164646044820152637265737360e01b60648201526084016108e2565b6000829050806001600160a01b031663284e97a9856000815181106137b9576137b9614074565b602002602001015130886000808d896040518863ffffffff1660e01b81526004016137ea97969594939291906145e6565b6020604051808303816000875af1158015613809573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061382d9190614210565b6138705760405162461bcd60e51b815260206004820152601460248201527311549497d253925512505312569157d09413d3d360621b60448201526064016108e2565b8360008151811061388357613883614074565b60200260200101516001600160a01b03166383b87e5a886000600281106138ac576138ac614074565b6020020151896001602002015186886003815181106138cd576138cd614074565b60200260200101518b6040518663ffffffff1660e01b81526004016138f695949392919061465f565b6020604051808303816000875af1158015613915573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139399190614210565b6139855760405162461bcd60e51b815260206004820152601a60248201527f4552525f494e495449414c495a455f534944455354414b494e4700000000000060448201526064016108e2565b5050949350505050565b6040516001600160a01b038085166024830152831660448201526064810182905261332a9085906323b872dd60e01b906084016132f3565b600061333c828461437d565b6000613a28826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316613b359092919063ffffffff16565b8051909150156119e05780806020019051810190613a469190614210565b6119e05760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016108e2565b6000808260601b9050604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81528160148201526e5af43d82803e903d91602b57fd5bf360881b60288201526037816000f06040516001600160a01b03821681529093507f117c72e6c25f0a072e36e148df71468ce2f3dbe7defec5b2c257a6e3eb65278c915060200160405180910390a150919050565b6060613b448484600085613b4c565b949350505050565b606082471015613bad5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016108e2565b843b613bfb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108e2565b600080866001600160a01b03168587604051613c1791906146c7565b60006040518083038185875af1925050503d8060008114613c54576040519150601f19603f3d011682016040523d82523d6000602084013e613c59565b606091505b5091509150613c69828286613c74565b979650505050505050565b60608315613c8357508161333c565b825115613c935782518084602001fd5b8160405162461bcd60e51b81526004016108e291906146e3565b6001600160a01b0381168114610b3657600080fd5b600060208284031215613cd457600080fd5b813561333c81613cad565b6020808252825182820181905260009190848201906040850190845b81811015613d205783516001600160a01b031683529284019291840191600101613cfb565b50909695505050505050565b600060208284031215613d3e57600080fd5b5035919050565b60008083601f840112613d5757600080fd5b50813567ffffffffffffffff811115613d6f57600080fd5b6020830191508360208260051b8501011115613d8a57600080fd5b9250929050565b600080600080600060608688031215613da957600080fd5b8535613db481613cad565b9450602086013567ffffffffffffffff80821115613dd157600080fd5b613ddd89838a01613d45565b90965094506040880135915080821115613df657600080fd5b50613e0388828901613d45565b969995985093965092949392505050565b60008060208385031215613e2757600080fd5b823567ffffffffffffffff80821115613e3f57600080fd5b818501915085601f830112613e5357600080fd5b813581811115613e6257600080fd5b866020606083028501011115613e7757600080fd5b60209290920196919550909350505050565b60008060008060808587031215613e9f57600080fd5b5050823594602084013594506040840135936060013592509050565b60008060008060008060c08789031215613ed457600080fd5b8635613edf81613cad565b95506020870135613eef81613cad565b945060408701359350606087013592506080870135613f0d81613cad565b915060a0870135613f1d81613cad565b809150509295509295509295565b60008060208385031215613f3e57600080fd5b823567ffffffffffffffff80821115613f5657600080fd5b818501915085601f830112613f6a57600080fd5b813581811115613f7957600080fd5b86602061014083028501011115613e7757600080fd5b600080600080600080600060a0888a031215613faa57600080fd5b6040880189811115613fbb57600080fd5b8897503567ffffffffffffffff80821115613fd557600080fd5b613fe18b838c01613d45565b909850965060608a0135915080821115613ffa57600080fd5b6140068b838c01613d45565b909650945060808a013591508082111561401f57600080fd5b5061402c8a828b01613d45565b989b979a50959850939692959293505050565b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561406f5761406f61403f565b500290565b634e487b7160e01b600052603260045260246000fd5b600060001982141561409e5761409e61403f565b5060010190565b60208082526016908201527527b1b2b0b72937baba32b91d102727aa1027aba722a960511b604082015260600190565b60208082526029908201527f466163746f7279526f757465723a20496e76616c6964205f64697370656e736560408201526872206164647265737360b81b606082015260800190565b6000828210156141305761413061403f565b500390565b634e487b7160e01b600052603160045260246000fd5b60208082526029908201527f466163746f7279526f757465723a20496e76616c6964205f666978656452617460408201526865206164647265737360b81b606082015260800190565b6000826141b157634e487b7160e01b600052601260045260246000fd5b500490565b6020808252602a908201527f466163746f7279526f757465723a20496e76616c6964205f7373436f6e7472616040820152696374206164647265737360b01b606082015260800190565b80518015158114611c2e57600080fd5b60006020828403121561422257600080fd5b61333c82614200565b6020808252602b908201527f464143544f525920524f555445523a204e4f54204f524947494e414c2045524360408201526a32302054454d504c41544560a81b606082015260800190565b6001600160a01b03868116825260606020808401829052908301869052600091879160808501845b898110156142c55784356142b181613cad565b84168252938201939082019060010161429e565b5085810360408701528681526001600160fb1b038711156142e557600080fd5b8660051b9350838883830137600093010191825250979650505050505050565b60006020828403121561431757600080fd5b5051919050565b60208082526022908201527f466163746f7279526f757465723a20546f6f204d616e79204f7065726174696f6040820152616e7360f01b606082015260800190565b60006020828403121561437257600080fd5b815161333c81613cad565b600082198211156143905761439061403f565b500190565b634e487b7160e01b600052602160045260246000fd5b6000602082840312156143bd57600080fd5b81356004811061333c57600080fd5b60e08101818460005b60038110156143fd5781516001600160a01b03168352602092830192909101906001016143d5565b505050606082018360005b6004811015614427578151835260209283019290910190600101614408565b5050509392505050565b6000806040838503121561444457600080fd5b505080516020909101519092909150565b600080600080600060a0868803121561446d57600080fd5b5050835160208501516040860151606087015160809097015192989197509594509092509050565b6000806000806000806000806000806000806101808d8f0312156144b857600080fd5b8c516144c381613cad565b60208e0151909c506144d481613cad565b60408e015160608f0151919c509a506144ec81613cad565b60808e015160a08f0151919a509850965061450960c08e01614200565b955060e08d015194506101008d015193506101208d015192506101408d015191506145376101608e01614200565b90509295989b509295989b509295989b565b6000806000806080858703121561455f57600080fd5b505082516020840151604085015160609095015191969095509092509050565b600081518084526020808501945080840160005b838110156145af57815187529582019590820190600101614593565b509495945050505050565b8060005b600181101561332a5781516001600160a01b03168452602093840193909101906001016145be565b600061010060018060a01b03808b1684526020818b16818601528260408601526146128386018b61457f565b93508815156060860152871515608086015260a0850192508660005b600281101561464d57815184168552938201939082019060010161462e565b5050505050612fc960e08301846145ba565b6001600160a01b038681168252858116602083015284811660408301528316606082015260a060808201819052600090613c699083018461457f565b60005b838110156146b657818101518382015260200161469e565b8381111561332a5750506000910152565b600082516146d981846020870161469b565b9190910192915050565b602081526000825180602084015261470281604085016020870161469b565b601f01601f1916919091016040019291505056fea2646970667358221220c67e8fca36a392ffc78255f877c99882c98a625746868858035b2cf86a93d1ba64736f6c634300080c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c7ec1970b09224b317c52d92f37f5e1e4ff6b687000000000000000000000000967da4048cd07ab37855c090aaf366e4ce1b9f480000000000000000000000008dac419d5d81af8c8e795d0d73f64d5220e28cd800000000000000000000000049e35cd2bae043abd9074b6e5a649a5adeb05c3300000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _routerOwner (address): 0xC7EC1970B09224B317c52d92f37F5e1E4fF6B687
Arg [1] : _oceanToken (address): 0x967da4048cD07aB37855c090aAF366e4ce1b9F48
Arg [2] : _bpoolTemplate (address): 0x8daC419D5D81Af8c8E795D0D73f64d5220e28cd8
Arg [3] : _opcCollector (address): 0x49E35cd2bAE043Abd9074B6e5a649a5AdEB05C33
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000c7ec1970b09224b317c52d92f37f5e1e4ff6b687
Arg [1] : 000000000000000000000000967da4048cd07ab37855c090aaf366e4ce1b9f48
Arg [2] : 0000000000000000000000008dac419d5d81af8c8e795d0d73f64d5220e28cd8
Arg [3] : 00000000000000000000000049e35cd2bae043abd9074b6e5a649a5adeb05c33
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ 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.