More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 26 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transfer | 14250826 | 930 days ago | IN | 0.0074489 ETH | 0.00322393 | ||||
Transfer | 14245041 | 931 days ago | IN | 0.004 ETH | 0.00152811 | ||||
Transfer | 13970622 | 973 days ago | IN | 0.0216932 ETH | 0.00317794 | ||||
Transfer | 13933787 | 979 days ago | IN | 0.0054895 ETH | 0.00322003 | ||||
Transfer | 13911051 | 983 days ago | IN | 0.266656 ETH | 0.00170472 | ||||
Transfer | 13898309 | 984 days ago | IN | 0.04 ETH | 0.00147322 | ||||
Transfer | 13869699 | 989 days ago | IN | 0.265 ETH | 0.00277807 | ||||
Transfer | 13844599 | 993 days ago | IN | 0.0332714 ETH | 0.00254656 | ||||
Transfer | 13826343 | 996 days ago | IN | 0.27 ETH | 0.00199548 | ||||
Transfer | 13825952 | 996 days ago | IN | 0.0079915 ETH | 0.00343049 | ||||
Transfer | 13747847 | 1008 days ago | IN | 0.03029737 ETH | 0.0023153 | ||||
Transfer | 13685513 | 1018 days ago | IN | 0.01254452 ETH | 0.00357782 | ||||
Claim Sell Order | 11385938 | 1374 days ago | IN | 0 ETH | 0.00372582 | ||||
Claim Buy Order | 11380870 | 1375 days ago | IN | 0 ETH | 0.001617 | ||||
Claim Sell Order | 11380596 | 1375 days ago | IN | 0 ETH | 0.00178968 | ||||
Claim Sell Order | 11380567 | 1375 days ago | IN | 0 ETH | 0.00101992 | ||||
Claim Sell Order | 11380430 | 1375 days ago | IN | 0 ETH | 0.00101992 | ||||
Claim Sell Order | 11380348 | 1375 days ago | IN | 0 ETH | 0.00101992 | ||||
Claim Sell Order | 11380307 | 1375 days ago | IN | 0 ETH | 0.00178968 | ||||
Claim Sell Order | 11380294 | 1375 days ago | IN | 0 ETH | 0.00178968 | ||||
Claim Sell Order | 11380201 | 1375 days ago | IN | 0 ETH | 0.00178968 | ||||
Claim Sell Order | 11380115 | 1375 days ago | IN | 0 ETH | 0.00101992 | ||||
Claim Sell Order | 11380106 | 1375 days ago | IN | 0 ETH | 0.00101992 | ||||
Claim Sell Order | 11380084 | 1375 days ago | IN | 0 ETH | 0.00178968 | ||||
Set Up Market | 11356503 | 1379 days ago | IN | 0 ETH | 0.00193106 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
14137322 | 948 days ago | 0.0161 ETH |
Loading...
Loading
Contract Name:
BatchedBancorMarketMaker
Compiler Version
v0.6.2+commit.bacdbe57
Optimization Enabled:
Yes with 1 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.6.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/math/SafeMath.sol"; import "./BancorFormula.sol"; import "./interfaces/IFundraisingController.sol"; import "./interfaces/ITap.sol"; import "./RewardToken.sol"; contract BatchedBancorMarketMaker is Ownable { using SafeMath for uint256; uint256 public constant PCT_BASE = 10 ** 18; // 0% = 0; 1% = 10 ** 16; 100% = 10 ** 18 uint32 public constant PPM = 1000000; struct Collateral { bool whitelisted; uint256 virtualSupply; uint256 virtualBalance; uint32 reserveRatio; uint256 slippage; } struct MetaBatch { bool initialized; uint256 realSupply; uint256 buyFeePct; uint256 sellFeePct; IBancorFormula formula; mapping(address => Batch) batches; } struct Batch { bool initialized; bool cancelled; uint256 supply; uint256 balance; uint32 reserveRatio; uint256 slippage; uint256 totalBuySpend; uint256 totalBuyReturn; uint256 totalSellSpend; uint256 totalSellReturn; mapping(address => uint256) buyers; mapping(address => uint256) sellers; } IFundraisingController public controller; ITap public tap; RewardToken public rewardToken; address public beneficiary; IBancorFormula public formula; IERC20 public DAI; uint256 public batchBlocks; uint256 public buyFeePct; uint256 public sellFeePct; bool public isOpen; uint256 public tokensToBeMinted; address public dao; mapping(address => uint256) public collateralsToBeClaimed; mapping(address => Collateral) public collaterals; mapping(uint256 => MetaBatch) public metaBatches; event UpdateBeneficiary (address indexed beneficiary); event UpdateFormula (address indexed formula); event UpdateFees (uint256 buyFeePct, uint256 sellFeePct); event NewMetaBatch (uint256 indexed id, uint256 supply, uint256 buyFeePct, uint256 sellFeePct, address formula); event NewBatch ( uint256 indexed id, address indexed collateral, uint256 supply, uint256 balance, uint32 reserveRatio, uint256 slippage) ; event CancelBatch (uint256 indexed id, address indexed collateral); event AddCollateralToken ( address indexed collateral, uint256 virtualSupply, uint256 virtualBalance, uint32 reserveRatio, uint256 slippage ); event RemoveCollateralToken (address indexed collateral); event UpdateCollateralToken ( address indexed collateral, uint256 virtualSupply, uint256 virtualBalance, uint32 reserveRatio, uint256 slippage ); event Open (); event paused (); event OpenBuyOrder (address indexed buyer, uint256 indexed batchId, address indexed collateral, uint256 fee, uint256 value); event OpenSellOrder (address indexed seller, uint256 indexed batchId, address indexed collateral, uint256 amount); event ClaimBuyOrder (address indexed buyer, uint256 indexed batchId, address indexed collateral, uint256 amount); event ClaimSellOrder (address indexed seller, uint256 indexed batchId, address indexed collateral, uint256 fee, uint256 value); event ClaimCancelledBuyOrder (address indexed buyer, uint256 indexed batchId, address indexed collateral, uint256 value); event ClaimCancelledSellOrder(address indexed seller, uint256 indexed batchId, address indexed collateral, uint256 amount); event UpdatePricing ( uint256 indexed batchId, address indexed collateral, uint256 totalBuySpend, uint256 totalBuyReturn, uint256 totalSellSpend, uint256 totalSellReturn ); /** * @dev Throws if called by any account other than the owner. */ modifier onlyDAO() { require(dao == msg.sender, "DAO: caller is not the DAO"); _; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyTAP() { require(address(tap) == msg.sender, "TAP: caller is not the Tap"); _; } /***** external function *****/ /** * @notice Initialize market maker * @param _beneficiary The address of the beneficiary [to whom fees are to be sent] * @param _formula The address of the BancorFormula [computation] contract * @param _batchBlocks The number of blocks batches are to last * @param _buyFeePct The fee to be deducted from buy orders [in PCT_BASE] * @param _sellFeePct The fee to be deducted from sell orders [in PCT_BASE] */ constructor( IBancorFormula _formula, RewardToken _rewardToken, IERC20 _dai, address _dao, address _beneficiary, uint256 _batchBlocks, uint256 _buyFeePct, uint256 _sellFeePct ) public { require(_batchBlocks > 0,"batchBlocks must be greater than zero"); require(_feeIsValid(_buyFeePct) && _feeIsValid(_sellFeePct), "Invalid Fee Percentage"); rewardToken = _rewardToken; formula = _formula; beneficiary = _beneficiary; batchBlocks = _batchBlocks; buyFeePct = _buyFeePct; sellFeePct = _sellFeePct; DAI = _dai; dao = _dao; } function setUpMarket( IFundraisingController _controller, ITap _tap ) public onlyOwner { controller = _controller; transferOwnership(address(_controller)); tap = _tap; open(); } /** * @notice Open market making [enabling users to open buy and sell orders] */ function open() internal { require(!isOpen, "Market is already open"); _open(); } /** * @notice pause market making [disabling users to open buy and sell orders] */ function pause() public onlyDAO { require(isOpen, "Market is already paused"); if(isOpen == false) { isOpen = true; } else { isOpen = false; } emit paused(); } /** * @notice Update formula to `_formula` * @param _formula The address of the new BancorFormula [computation] contract */ function updateFormula(IBancorFormula _formula) external onlyOwner { _updateFormula(_formula); } /** * @notice Update beneficiary to `_beneficiary` * @param _beneficiary The address of the new beneficiary [to whom fees are to be sent] */ function updateBeneficiary(address _beneficiary) external onlyOwner { require(_beneficiaryIsValid(_beneficiary), "Invalid Beneficiary Address"); _updateBeneficiary(_beneficiary); } /** * @notice Update fees deducted from buy and sell orders to respectively `@formatPct(_buyFeePct)`% and `@formatPct(_sellFeePct)`% * @param _buyFeePct The new fee to be deducted from buy orders [in PCT_BASE] * @param _sellFeePct The new fee to be deducted from sell orders [in PCT_BASE] */ function updateFees(uint256 _buyFeePct, uint256 _sellFeePct) external onlyOwner { require(_feeIsValid(_buyFeePct) && _feeIsValid(_sellFeePct), "Invalid Fee Percentage"); _updateFees(_buyFeePct, _sellFeePct); } /* collateral tokens related functions */ /** * @notice Add `_collateral.symbol(): string` as a whitelisted collateral token * @param _collateral The address of the collateral token to be whitelisted * @param _virtualSupply The virtual supply to be used for that collateral token [in wei] * @param _virtualBalance The virtual balance to be used for that collateral token [in wei] * @param _reserveRatio The reserve ratio to be used for that collateral token [in PPM] * @param _slippage The price slippage below which each batch is to be kept for that collateral token [in PCT_BASE] */ function addCollateralToken(address _collateral, uint256 _virtualSupply, uint256 _virtualBalance, uint32 _reserveRatio, uint256 _slippage) external onlyOwner { require(!_collateralIsWhitelisted(_collateral), "Token is already whitelisted"); require(_reserveRatioIsValid(_reserveRatio), "Invalid Reserve Ratio"); _addCollateralToken(_collateral, _virtualSupply, _virtualBalance, _reserveRatio, _slippage); } /** * @notice Remove `_collateral.symbol(): string` as a whitelisted collateral token * @param _collateral The address of the collateral token to be un-whitelisted */ function removeCollateralToken(address _collateral) external onlyOwner { require(_collateralIsWhitelisted(_collateral), "Token is not whitelisted"); _removeCollateralToken(_collateral); } /** * @notice Update `_collateral.symbol(): string` collateralization settings * @param _collateral The address of the collateral token whose collateralization settings are to be updated * @param _virtualSupply The new virtual supply to be used for that collateral token [in wei] * @param _virtualBalance The new virtual balance to be used for that collateral token [in wei] * @param _reserveRatio The new reserve ratio to be used for that collateral token [in PPM] * @param _slippage The new price slippage below which each batch is to be kept for that collateral token [in PCT_BASE] */ function updateCollateralToken(address _collateral, uint256 _virtualSupply, uint256 _virtualBalance, uint32 _reserveRatio, uint256 _slippage) external onlyOwner { require(_collateralIsWhitelisted(_collateral), "Token is not whitelisted"); require(_reserveRatioIsValid(_reserveRatio), "Invalid Reserve Ratio"); _updateCollateralToken(_collateral, _virtualSupply, _virtualBalance, _reserveRatio, _slippage); } /* market making related functions */ /** * @notice Open a buy order worth `@tokenAmount(_collateral, _value)` * @param _buyer The address of the buyer * @param _collateral The address of the collateral token to be spent * @param _value The amount of collateral token to be spent */ function openBuyOrder(address _buyer, address _collateral, uint256 _value) external payable onlyOwner { require(isOpen, "Market is not open"); require(_collateralIsWhitelisted(_collateral), "Token is not whitelisted"); require(!_batchIsCancelled(_currentBatchId(), _collateral), "Batch cancled"); require(_collateralValueIsValid(_buyer, _collateral, _value), "Invalid Collateral Value"); _openBuyOrder(_buyer, _collateral, _value); } /** * @notice Open a sell order worth `@tokenAmount(self.token(): address, _amount)` against `_collateral.symbol(): string` * @param _seller The address of the seller * @param _collateral The address of the collateral token to be returned * @param _amount The amount of bonded token to be spent */ function openSellOrder(address _seller, address _collateral, uint256 _amount) external onlyOwner { require(isOpen, "Is not open"); require(_collateralIsWhitelisted(_collateral), "Collateral is not Whitelisted"); require(!_batchIsCancelled(_currentBatchId(), _collateral), "Batch is cancled"); require(_bondAmountIsValid(_seller, _amount), "Invalid bond amount"); _openSellOrder(_seller, _collateral, _amount); } /** * @notice Claim the results of `_buyer`'s `_collateral.symbol(): string` buy orders from batch #`_batchId` * @param _buyer The address of the user whose buy orders are to be claimed * @param _batchId The id of the batch in which buy orders are to be claimed * @param _collateral The address of the collateral token against which buy orders are to be claimed */ function claimBuyOrder(address _buyer, uint256 _batchId, address _collateral) external { require(_collateralIsWhitelisted(_collateral), "Collateral Not Whitelisted"); require(_batchIsOver(_batchId), "Batch is over"); require(!_batchIsCancelled(_batchId, _collateral),"Batch is cancled"); require(_userIsBuyer(_batchId, _collateral, _buyer), "Nothing to claim"); _claimBuyOrder(_buyer, _batchId, _collateral); } /** * @notice Claim the results of `_seller`'s `_collateral.symbol(): string` sell orders from batch #`_batchId` * @param _seller The address of the user whose sell orders are to be claimed * @param _batchId The id of the batch in which sell orders are to be claimed * @param _collateral The address of the collateral token against which sell orders are to be claimed */ function claimSellOrder(address _seller, uint256 _batchId, address _collateral) external { require(_collateralIsWhitelisted(_collateral), "Collateral Not Whitelisted"); require(_batchIsOver(_batchId), "Batch is over"); require(!_batchIsCancelled(_batchId, _collateral),"Batch is cancled"); require(_userIsSeller(_batchId, _collateral, _seller), "Nothing to claim"); _claimSellOrder(_seller, _batchId, _collateral); } /** * @notice Claim the investments of `_buyer`'s `_collateral.symbol(): string` buy orders from cancelled batch #`_batchId` * @param _buyer The address of the user whose cancelled buy orders are to be claimed * @param _batchId The id of the batch in which cancelled buy orders are to be claimed * @param _collateral The address of the collateral token against which cancelled buy orders are to be claimed */ function claimCancelledBuyOrder(address _buyer, uint256 _batchId, address _collateral) external { require(_batchIsCancelled(_batchId, _collateral), "Batch is not cancled"); require(_userIsBuyer(_batchId, _collateral, _buyer), "Nothing to claim"); _claimCancelledBuyOrder(_buyer, _batchId, _collateral); } /** * @notice Claim the investments of `_seller`'s `_collateral.symbol(): string` sell orders from cancelled batch #`_batchId` * @param _seller The address of the user whose cancelled sell orders are to be claimed * @param _batchId The id of the batch in which cancelled sell orders are to be claimed * @param _collateral The address of the collateral token against which cancelled sell orders are to be claimed */ function claimCancelledSellOrder(address _seller, uint256 _batchId, address _collateral) external { require(_batchIsCancelled(_batchId, _collateral), "Batch not cancled"); require(_userIsSeller(_batchId, _collateral, _seller), "Nothing to claim"); _claimCancelledSellOrder(_seller, _batchId, _collateral); } /***** public view functions *****/ function getCurrentBatchId() public view returns (uint256) { return _currentBatchId(); } function getCollateralToken(address _collateral) public view returns (bool, uint256, uint256, uint32, uint256) { Collateral storage collateral = collaterals[_collateral]; return (collateral.whitelisted, collateral.virtualSupply, collateral.virtualBalance, collateral.reserveRatio, collateral.slippage); } function getBatch(uint256 _batchId, address _collateral) public view returns (bool, bool, uint256, uint256, uint32, uint256, uint256, uint256, uint256, uint256) { Batch storage batch = metaBatches[_batchId].batches[_collateral]; return ( batch.initialized, batch.cancelled, batch.supply, batch.balance, batch.reserveRatio, batch.slippage, batch.totalBuySpend, batch.totalBuyReturn, batch.totalSellSpend, batch.totalSellReturn ); } function getStaticPricePPM(uint256 _supply, uint256 _balance, uint32 _reserveRatio) public pure returns (uint256) { return _staticPricePPM(_supply, _balance, _reserveRatio); } /***** internal functions *****/ /* computation functions */ function _staticPricePPM(uint256 _supply, uint256 _balance, uint32 _reserveRatio) internal pure returns (uint256) { return uint256(PPM).mul(uint256(PPM)).mul(_balance).div(_supply.mul(uint256(_reserveRatio))); } function _currentBatchId() internal view returns (uint256) { return (block.number.div(batchBlocks)).mul(batchBlocks); } /* check functions */ function _beneficiaryIsValid(address _beneficiary) internal pure returns (bool) { return _beneficiary != address(0); } function _feeIsValid(uint256 _fee) internal pure returns (bool) { return _fee < PCT_BASE; } function _reserveRatioIsValid(uint32 _reserveRatio) internal pure returns (bool) { return _reserveRatio <= PPM; } function _collateralValueIsValid(address _buyer, address _collateral, uint256 _value) internal view returns (bool) { if (_value == 0) { return false; } IERC20 token = IERC20(_collateral); return ( token.balanceOf(_buyer) >= _value && token.allowance(_buyer, address(this)) >= _value ); } function _bondAmountIsValid(address _seller, uint256 _amount) internal view returns (bool) { return _amount != 0 && rewardToken.balanceOf(_seller) >= _amount; } function _collateralIsWhitelisted(address _collateral) internal view returns (bool) { return collaterals[_collateral].whitelisted; } function _batchIsOver(uint256 _batchId) internal view returns (bool) { return _batchId < _currentBatchId(); } function _batchIsCancelled(uint256 _batchId, address _collateral) internal view returns (bool) { return metaBatches[_batchId].batches[_collateral].cancelled; } function _userIsBuyer(uint256 _batchId, address _collateral, address _user) internal view returns (bool) { Batch storage batch = metaBatches[_batchId].batches[_collateral]; return batch.buyers[_user] > 0; } function _userIsSeller(uint256 _batchId, address _collateral, address _user) internal view returns (bool) { Batch storage batch = metaBatches[_batchId].batches[_collateral]; return batch.sellers[_user] > 0; } function _poolBalanceIsSufficient(address _collateral) internal view returns (bool) { IERC20 token = IERC20(_collateral); return token.balanceOf(address(this)) >= collateralsToBeClaimed[_collateral]; } function _slippageIsValid(Batch storage _batch) internal view returns (bool) { uint256 staticPricePPM = _staticPricePPM(_batch.supply, _batch.balance, _batch.reserveRatio); uint256 maximumSlippage = _batch.slippage; // if static price is zero let's consider that every slippage is valid if (staticPricePPM == 0) { return true; } return _buySlippageIsValid(_batch, staticPricePPM, maximumSlippage) && _sellSlippageIsValid(_batch, staticPricePPM, maximumSlippage); } function _buySlippageIsValid(Batch storage _batch, uint256 _startingPricePPM, uint256 _maximumSlippage) internal view returns (bool) { /** * NOTE * the case where starting price is zero is handled * in the meta function _slippageIsValid() */ /** * NOTE * slippage is valid if: * totalBuyReturn >= totalBuySpend / (startingPrice * (1 + maxSlippage)) * totalBuyReturn >= totalBuySpend / ((startingPricePPM / PPM) * (1 + maximumSlippage / PCT_BASE)) * totalBuyReturn >= totalBuySpend / ((startingPricePPM / PPM) * (1 + maximumSlippage / PCT_BASE)) * totalBuyReturn >= totalBuySpend / ((startingPricePPM / PPM) * (PCT + maximumSlippage) / PCT_BASE) * totalBuyReturn * startingPrice * ( PCT + maximumSlippage) >= totalBuySpend * PCT_BASE * PPM */ if ( _batch.totalBuyReturn.mul(_startingPricePPM).mul(PCT_BASE.add(_maximumSlippage)) >= _batch.totalBuySpend.mul(PCT_BASE).mul(uint256(PPM)) ) { return true; } return false; } function _sellSlippageIsValid(Batch storage _batch, uint256 _startingPricePPM, uint256 _maximumSlippage) internal view returns (bool) { /** * NOTE * the case where starting price is zero is handled * in the meta function _slippageIsValid() */ // if allowed sell slippage >= 100% // then any sell slippage is valid if (_maximumSlippage >= PCT_BASE) { return true; } /** * NOTE * slippage is valid if * totalSellReturn >= startingPrice * (1 - maxSlippage) * totalBuySpend * totalSellReturn >= (startingPricePPM / PPM) * (1 - maximumSlippage / PCT_BASE) * totalBuySpend * totalSellReturn >= (startingPricePPM / PPM) * (PCT_BASE - maximumSlippage) * totalBuySpend / PCT_BASE * totalSellReturn * PCT_BASE * PPM = startingPricePPM * (PCT_BASE - maximumSlippage) * totalBuySpend */ if ( _batch.totalSellReturn.mul(PCT_BASE).mul(uint256(PPM)) >= _startingPricePPM.mul(PCT_BASE.sub(_maximumSlippage)).mul(_batch.totalSellSpend) ) { return true; } return false; } /* initialization functions */ function _currentBatch(address _collateral) internal returns (uint256, Batch storage) { uint256 batchId = _currentBatchId(); MetaBatch storage metaBatch = metaBatches[batchId]; Batch storage batch = metaBatch.batches[_collateral]; if (!metaBatch.initialized) { /** * NOTE * all collateral batches should be initialized with the same supply to * avoid price manipulation between different collaterals in the same meta-batch * we don't need to do the same with collateral balances as orders against one collateral * can't affect the pool's balance against another collateral and tap is a step-function * of the meta-batch duration */ /** * NOTE * realSupply(metaBatch) = totalSupply(metaBatchInitialization) + tokensToBeMinted(metaBatchInitialization) * 1. buy and sell orders incoming during the current meta-batch and affecting totalSupply or tokensToBeMinted * should not be taken into account in the price computation [they are already a part of the batched pricing computation] * 2. the only way for totalSupply to be modified during a meta-batch [outside of incoming buy and sell orders] * is for buy orders from previous meta-batches to be claimed [and tokens to be minted]: * as such totalSupply(metaBatch) + tokenToBeMinted(metaBatch) will always equal totalSupply(metaBatchInitialization) + tokenToBeMinted(metaBatchInitialization) */ metaBatch.realSupply = rewardToken.totalSupply().add(tokensToBeMinted); metaBatch.buyFeePct = buyFeePct; metaBatch.sellFeePct = sellFeePct; metaBatch.formula = formula; metaBatch.initialized = true; emit NewMetaBatch(batchId, metaBatch.realSupply, metaBatch.buyFeePct, metaBatch.sellFeePct, address(metaBatch.formula)); } if (!batch.initialized) { /** * NOTE * supply(batch) = realSupply(metaBatch) + virtualSupply(batchInitialization) * virtualSupply can technically be updated during a batch: the on-going batch will still use * its value at the time of initialization [it's up to the updater to act wisely] */ /** * NOTE * balance(batch) = poolBalance(batchInitialization) - collateralsToBeClaimed(batchInitialization) + virtualBalance(metaBatchInitialization) * 1. buy and sell orders incoming during the current batch and affecting poolBalance or collateralsToBeClaimed * should not be taken into account in the price computation [they are already a part of the batched price computation] * 2. the only way for poolBalance to be modified during a batch [outside of incoming buy and sell orders] * is for sell orders from previous meta-batches to be claimed [and collateral to be transfered] as the tap is a step-function of the meta-batch duration: * as such poolBalance(batch) - collateralsToBeClaimed(batch) will always equal poolBalance(batchInitialization) - collateralsToBeClaimed(batchInitialization) * 3. virtualBalance can technically be updated during a batch: the on-going batch will still use * its value at the time of initialization [it's up to the updater to act wisely] */ IERC20 token = IERC20(_collateral); controller.updateTappedAmount(_collateral); batch.supply = metaBatch.realSupply.add(collaterals[_collateral].virtualSupply); batch.balance = token.balanceOf(address(this)).add(collaterals[_collateral].virtualBalance).sub(collateralsToBeClaimed[_collateral]); batch.reserveRatio = collaterals[_collateral].reserveRatio; batch.slippage = collaterals[_collateral].slippage; batch.initialized = true; emit NewBatch(batchId, _collateral, batch.supply, batch.balance, batch.reserveRatio, batch.slippage); } return (batchId, batch); } /* state modifiying functions */ function _open() internal { isOpen = true; emit Open(); } function _updateBeneficiary(address _beneficiary) internal { beneficiary = _beneficiary; emit UpdateBeneficiary(_beneficiary); } function _updateFormula(IBancorFormula _formula) internal { formula = _formula; emit UpdateFormula(address(_formula)); } function _updateFees(uint256 _buyFeePct, uint256 _sellFeePct) internal { buyFeePct = _buyFeePct; sellFeePct = _sellFeePct; emit UpdateFees(_buyFeePct, _sellFeePct); } function _cancelCurrentBatch(address _collateral) internal { (uint256 batchId, Batch storage batch) = _currentBatch(_collateral); if (!batch.cancelled) { batch.cancelled = true; // bought bonds are cancelled but sold bonds are due back // bought collaterals are cancelled but sold collaterals are due back tokensToBeMinted = tokensToBeMinted.sub(batch.totalBuyReturn).add(batch.totalSellSpend); collateralsToBeClaimed[_collateral] = collateralsToBeClaimed[_collateral].add(batch.totalBuySpend).sub(batch.totalSellReturn); emit CancelBatch(batchId, _collateral); } } function _addCollateralToken(address _collateral, uint256 _virtualSupply, uint256 _virtualBalance, uint32 _reserveRatio, uint256 _slippage) internal { collaterals[_collateral].whitelisted = true; collaterals[_collateral].virtualSupply = _virtualSupply; collaterals[_collateral].virtualBalance = _virtualBalance; collaterals[_collateral].reserveRatio = _reserveRatio; collaterals[_collateral].slippage = _slippage; emit AddCollateralToken(_collateral, _virtualSupply, _virtualBalance, _reserveRatio, _slippage); } function _removeCollateralToken(address _collateral) internal { _cancelCurrentBatch(_collateral); Collateral storage collateral = collaterals[_collateral]; delete collateral.whitelisted; delete collateral.virtualSupply; delete collateral.virtualBalance; delete collateral.reserveRatio; delete collateral.slippage; emit RemoveCollateralToken(_collateral); } function _updateCollateralToken( address _collateral, uint256 _virtualSupply, uint256 _virtualBalance, uint32 _reserveRatio, uint256 _slippage ) internal { collaterals[_collateral].virtualSupply = _virtualSupply; collaterals[_collateral].virtualBalance = _virtualBalance; collaterals[_collateral].reserveRatio = _reserveRatio; collaterals[_collateral].slippage = _slippage; emit UpdateCollateralToken(_collateral, _virtualSupply, _virtualBalance, _reserveRatio, _slippage); } function _openBuyOrder(address _buyer, address _collateral, uint256 _value) internal { (uint256 batchId, Batch storage batch) = _currentBatch(_collateral); // deduct fee uint256 fee = _value.mul(metaBatches[batchId].buyFeePct).div(PCT_BASE); uint256 value = _value.sub(fee); // collect fee and collateral if (fee > 0) { _transfer(_buyer, beneficiary, _collateral, fee); } _transfer(_buyer, address(this), _collateral, value); // save batch uint256 deprecatedBuyReturn = batch.totalBuyReturn; uint256 deprecatedSellReturn = batch.totalSellReturn; // update batch batch.totalBuySpend = batch.totalBuySpend.add(value); batch.buyers[_buyer] = batch.buyers[_buyer].add(value); // update pricing _updatePricing(batch, batchId, _collateral); // update the amount of tokens to be minted and collaterals to be claimed tokensToBeMinted = tokensToBeMinted.sub(deprecatedBuyReturn).add(batch.totalBuyReturn); collateralsToBeClaimed[_collateral] = collateralsToBeClaimed[_collateral].sub(deprecatedSellReturn).add(batch.totalSellReturn); // sanity checks require(_slippageIsValid(batch), "Slippage exceeds limit"); emit OpenBuyOrder(_buyer, batchId, _collateral, fee, value); } function _openSellOrder(address _seller, address _collateral, uint256 _amount) internal { (uint256 batchId, Batch storage batch) = _currentBatch(_collateral); // burn bonds rewardToken.burn(_seller, _amount); // save batch uint256 deprecatedBuyReturn = batch.totalBuyReturn; uint256 deprecatedSellReturn = batch.totalSellReturn; // update batch batch.totalSellSpend = batch.totalSellSpend.add(_amount); batch.sellers[_seller] = batch.sellers[_seller].add(_amount); // update pricing _updatePricing(batch, batchId, _collateral); // update the amount of tokens to be minted and collaterals to be claimed tokensToBeMinted = tokensToBeMinted.sub(deprecatedBuyReturn).add(batch.totalBuyReturn); collateralsToBeClaimed[_collateral] = collateralsToBeClaimed[_collateral].sub(deprecatedSellReturn).add(batch.totalSellReturn); // sanity checks require(_slippageIsValid(batch), "Slippage exceeds limit"); require(_poolBalanceIsSufficient(_collateral), "Insufficient pool balance"); emit OpenSellOrder(_seller, batchId, _collateral, _amount); } function _claimBuyOrder(address _buyer, uint256 _batchId, address _collateral) internal { Batch storage batch = metaBatches[_batchId].batches[_collateral]; uint256 buyReturn = (batch.buyers[_buyer].mul(batch.totalBuyReturn)).div(batch.totalBuySpend); batch.buyers[_buyer] = 0; if (buyReturn > 0) { tokensToBeMinted = tokensToBeMinted.sub(buyReturn); rewardToken.mint(_buyer, buyReturn); } emit ClaimBuyOrder(_buyer, _batchId, _collateral, buyReturn); } function _claimSellOrder(address _seller, uint256 _batchId, address _collateral) internal { Batch storage batch = metaBatches[_batchId].batches[_collateral]; uint256 saleReturn = (batch.sellers[_seller].mul(batch.totalSellReturn)).div(batch.totalSellSpend); uint256 fee = saleReturn.mul(metaBatches[_batchId].sellFeePct).div(PCT_BASE); uint256 value = saleReturn.sub(fee); IERC20 token = IERC20(_collateral); batch.sellers[_seller] = 0; if (value > 0) { collateralsToBeClaimed[_collateral] = collateralsToBeClaimed[_collateral].sub(saleReturn); token.transfer( _seller, value); } if (fee > 0) { token.transfer( beneficiary, fee); } emit ClaimSellOrder(_seller, _batchId, _collateral, fee, value); } function _claimCancelledBuyOrder(address _buyer, uint256 _batchId, address _collateral) internal { Batch storage batch = metaBatches[_batchId].batches[_collateral]; uint256 value = batch.buyers[_buyer]; batch.buyers[_buyer] = 0; if (value > 0) { collateralsToBeClaimed[_collateral] = collateralsToBeClaimed[_collateral].sub(value); IERC20 token = IERC20(_collateral); token.transfer( _buyer, value); } emit ClaimCancelledBuyOrder(_buyer, _batchId, _collateral, value); } function _claimCancelledSellOrder(address _seller, uint256 _batchId, address _collateral) internal { Batch storage batch = metaBatches[_batchId].batches[_collateral]; uint256 amount = batch.sellers[_seller]; batch.sellers[_seller] = 0; if (amount > 0) { tokensToBeMinted = tokensToBeMinted.sub(amount); rewardToken.mint(_seller, amount); } emit ClaimCancelledSellOrder(_seller, _batchId, _collateral, amount); } function _updatePricing(Batch storage batch, uint256 _batchId, address _collateral) internal { // the situation where there are no buy nor sell orders can't happen [keep commented] // if (batch.totalSellSpend == 0 && batch.totalBuySpend == 0) // return; // static price is the current exact price in collateral // per token according to the initial state of the batch // [expressed in PPM for precision sake] uint256 staticPricePPM = _staticPricePPM(batch.supply, batch.balance, batch.reserveRatio); // [NOTE] // if staticPrice is zero then resultOfSell [= 0] <= batch.totalBuySpend // so totalSellReturn will be zero and totalBuyReturn will be // computed normally along the formula // 1. we want to find out if buy orders are worth more sell orders [or vice-versa] // 2. we thus check the return of sell orders at the current exact price // 3. if the return of sell orders is larger than the pending buys, // there are more sells than buys [and vice-versa] uint256 resultOfSell = batch.totalSellSpend.mul(staticPricePPM).div(uint256(PPM)); if (resultOfSell > batch.totalBuySpend) { // >> sell orders are worth more than buy orders // 1. first we execute all pending buy orders at the current exact // price because there is at least one sell order for each buy order // 2. then the final sell return is the addition of this first // matched return with the remaining bonding curve return // the number of tokens bought as a result of all buy orders matched at the // current exact price [which is less than the total amount of tokens to be sold] batch.totalBuyReturn = batch.totalBuySpend.mul(uint256(PPM)).div(staticPricePPM); // the number of tokens left over to be sold along the curve which is the difference // between the original total sell order and the result of all the buy orders uint256 remainingSell = batch.totalSellSpend.sub(batch.totalBuyReturn); // the amount of collateral generated by selling tokens left over to be sold // along the bonding curve in the batch initial state [as if the buy orders // never existed and the sell order was just smaller than originally thought] uint256 remainingSellReturn = metaBatches[_batchId].formula.calculateSaleReturn(batch.supply, batch.balance, batch.reserveRatio, remainingSell); // the total result of all sells is the original amount of buys which were matched // plus the remaining sells which were executed along the bonding curve batch.totalSellReturn = batch.totalBuySpend.add(remainingSellReturn); } else { // >> buy orders are worth more than sell orders // 1. first we execute all pending sell orders at the current exact // price because there is at least one buy order for each sell order // 2. then the final buy return is the addition of this first // matched return with the remaining bonding curve return // the number of collaterals bought as a result of all sell orders matched at the // current exact price [which is less than the total amount of collateral to be spent] batch.totalSellReturn = resultOfSell; // the number of collaterals left over to be spent along the curve which is the difference // between the original total buy order and the result of all the sell orders uint256 remainingBuy = batch.totalBuySpend.sub(resultOfSell); // the amount of tokens generated by selling collaterals left over to be spent // along the bonding curve in the batch initial state [as if the sell orders // never existed and the buy order was just smaller than originally thought] uint256 remainingBuyReturn = metaBatches[_batchId].formula.calculatePurchaseReturn(batch.supply, batch.balance, batch.reserveRatio, remainingBuy); // the total result of all buys is the original amount of buys which were matched // plus the remaining buys which were executed along the bonding curve batch.totalBuyReturn = batch.totalSellSpend.add(remainingBuyReturn); } emit UpdatePricing(_batchId, _collateral, batch.totalBuySpend, batch.totalBuyReturn, batch.totalSellSpend, batch.totalSellReturn); } function _transfer(address _from, address _to, address _collateralToken, uint256 _amount) internal { require(IERC20(_collateralToken).transferFrom(_from, _to, _amount), "Transfer From Failed"); } function transfer(address _collateralToken, uint256 _amount) public onlyTAP { IERC20(_collateralToken).transfer( beneficiary, _amount); } }
pragma solidity ^0.6.0; import './interfaces/IBancorFormula.sol'; import "@openzeppelin/contracts/math/SafeMath.sol"; import './utility/Utils.sol'; contract BancorFormula is IBancorFormula, Utils { using SafeMath for uint256; string public version = '0.3'; uint256 private constant ONE = 1; uint32 private constant MAX_WEIGHT = 1000000; uint8 private constant MIN_PRECISION = 32; uint8 private constant MAX_PRECISION = 127; /** Auto-generated via 'PrintIntScalingFactors.py' */ uint256 private constant FIXED_1 = 0x080000000000000000000000000000000; uint256 private constant FIXED_2 = 0x100000000000000000000000000000000; uint256 private constant MAX_NUM = 0x200000000000000000000000000000000; /** Auto-generated via 'PrintLn2ScalingFactors.py' */ uint256 private constant LN2_NUMERATOR = 0x3f80fe03f80fe03f80fe03f80fe03f8; uint256 private constant LN2_DENOMINATOR = 0x5b9de1d10bf4103d647b0955897ba80; /** Auto-generated via 'PrintFunctionOptimalLog.py' and 'PrintFunctionOptimalExp.py' */ uint256 private constant OPT_LOG_MAX_VAL = 0x15bf0a8b1457695355fb8ac404e7a79e3; uint256 private constant OPT_EXP_MAX_VAL = 0x800000000000000000000000000000000; /** Auto-generated via 'PrintFunctionConstructor.py' */ uint256[128] private maxExpArray; constructor() public { // maxExpArray[ 0] = 0x6bffffffffffffffffffffffffffffffff; // maxExpArray[ 1] = 0x67ffffffffffffffffffffffffffffffff; // maxExpArray[ 2] = 0x637fffffffffffffffffffffffffffffff; // maxExpArray[ 3] = 0x5f6fffffffffffffffffffffffffffffff; // maxExpArray[ 4] = 0x5b77ffffffffffffffffffffffffffffff; // maxExpArray[ 5] = 0x57b3ffffffffffffffffffffffffffffff; // maxExpArray[ 6] = 0x5419ffffffffffffffffffffffffffffff; // maxExpArray[ 7] = 0x50a2ffffffffffffffffffffffffffffff; // maxExpArray[ 8] = 0x4d517fffffffffffffffffffffffffffff; // maxExpArray[ 9] = 0x4a233fffffffffffffffffffffffffffff; // maxExpArray[ 10] = 0x47165fffffffffffffffffffffffffffff; // maxExpArray[ 11] = 0x4429afffffffffffffffffffffffffffff; // maxExpArray[ 12] = 0x415bc7ffffffffffffffffffffffffffff; // maxExpArray[ 13] = 0x3eab73ffffffffffffffffffffffffffff; // maxExpArray[ 14] = 0x3c1771ffffffffffffffffffffffffffff; // maxExpArray[ 15] = 0x399e96ffffffffffffffffffffffffffff; // maxExpArray[ 16] = 0x373fc47fffffffffffffffffffffffffff; // maxExpArray[ 17] = 0x34f9e8ffffffffffffffffffffffffffff; // maxExpArray[ 18] = 0x32cbfd5fffffffffffffffffffffffffff; // maxExpArray[ 19] = 0x30b5057fffffffffffffffffffffffffff; // maxExpArray[ 20] = 0x2eb40f9fffffffffffffffffffffffffff; // maxExpArray[ 21] = 0x2cc8340fffffffffffffffffffffffffff; // maxExpArray[ 22] = 0x2af09481ffffffffffffffffffffffffff; // maxExpArray[ 23] = 0x292c5bddffffffffffffffffffffffffff; // maxExpArray[ 24] = 0x277abdcdffffffffffffffffffffffffff; // maxExpArray[ 25] = 0x25daf6657fffffffffffffffffffffffff; // maxExpArray[ 26] = 0x244c49c65fffffffffffffffffffffffff; // maxExpArray[ 27] = 0x22ce03cd5fffffffffffffffffffffffff; // maxExpArray[ 28] = 0x215f77c047ffffffffffffffffffffffff; // maxExpArray[ 29] = 0x1fffffffffffffffffffffffffffffffff; // maxExpArray[ 30] = 0x1eaefdbdabffffffffffffffffffffffff; // maxExpArray[ 31] = 0x1d6bd8b2ebffffffffffffffffffffffff; maxExpArray[ 32] = 0x1c35fedd14ffffffffffffffffffffffff; maxExpArray[ 33] = 0x1b0ce43b323fffffffffffffffffffffff; maxExpArray[ 34] = 0x19f0028ec1ffffffffffffffffffffffff; maxExpArray[ 35] = 0x18ded91f0e7fffffffffffffffffffffff; maxExpArray[ 36] = 0x17d8ec7f0417ffffffffffffffffffffff; maxExpArray[ 37] = 0x16ddc6556cdbffffffffffffffffffffff; maxExpArray[ 38] = 0x15ecf52776a1ffffffffffffffffffffff; maxExpArray[ 39] = 0x15060c256cb2ffffffffffffffffffffff; maxExpArray[ 40] = 0x1428a2f98d72ffffffffffffffffffffff; maxExpArray[ 41] = 0x13545598e5c23fffffffffffffffffffff; maxExpArray[ 42] = 0x1288c4161ce1dfffffffffffffffffffff; maxExpArray[ 43] = 0x11c592761c666fffffffffffffffffffff; maxExpArray[ 44] = 0x110a688680a757ffffffffffffffffffff; maxExpArray[ 45] = 0x1056f1b5bedf77ffffffffffffffffffff; maxExpArray[ 46] = 0x0faadceceeff8bffffffffffffffffffff; maxExpArray[ 47] = 0x0f05dc6b27edadffffffffffffffffffff; maxExpArray[ 48] = 0x0e67a5a25da4107fffffffffffffffffff; maxExpArray[ 49] = 0x0dcff115b14eedffffffffffffffffffff; maxExpArray[ 50] = 0x0d3e7a392431239fffffffffffffffffff; maxExpArray[ 51] = 0x0cb2ff529eb71e4fffffffffffffffffff; maxExpArray[ 52] = 0x0c2d415c3db974afffffffffffffffffff; maxExpArray[ 53] = 0x0bad03e7d883f69bffffffffffffffffff; maxExpArray[ 54] = 0x0b320d03b2c343d5ffffffffffffffffff; maxExpArray[ 55] = 0x0abc25204e02828dffffffffffffffffff; maxExpArray[ 56] = 0x0a4b16f74ee4bb207fffffffffffffffff; maxExpArray[ 57] = 0x09deaf736ac1f569ffffffffffffffffff; maxExpArray[ 58] = 0x0976bd9952c7aa957fffffffffffffffff; maxExpArray[ 59] = 0x09131271922eaa606fffffffffffffffff; maxExpArray[ 60] = 0x08b380f3558668c46fffffffffffffffff; maxExpArray[ 61] = 0x0857ddf0117efa215bffffffffffffffff; maxExpArray[ 62] = 0x07ffffffffffffffffffffffffffffffff; maxExpArray[ 63] = 0x07abbf6f6abb9d087fffffffffffffffff; maxExpArray[ 64] = 0x075af62cbac95f7dfa7fffffffffffffff; maxExpArray[ 65] = 0x070d7fb7452e187ac13fffffffffffffff; maxExpArray[ 66] = 0x06c3390ecc8af379295fffffffffffffff; maxExpArray[ 67] = 0x067c00a3b07ffc01fd6fffffffffffffff; maxExpArray[ 68] = 0x0637b647c39cbb9d3d27ffffffffffffff; maxExpArray[ 69] = 0x05f63b1fc104dbd39587ffffffffffffff; maxExpArray[ 70] = 0x05b771955b36e12f7235ffffffffffffff; maxExpArray[ 71] = 0x057b3d49dda84556d6f6ffffffffffffff; maxExpArray[ 72] = 0x054183095b2c8ececf30ffffffffffffff; maxExpArray[ 73] = 0x050a28be635ca2b888f77fffffffffffff; maxExpArray[ 74] = 0x04d5156639708c9db33c3fffffffffffff; maxExpArray[ 75] = 0x04a23105873875bd52dfdfffffffffffff; maxExpArray[ 76] = 0x0471649d87199aa990756fffffffffffff; maxExpArray[ 77] = 0x04429a21a029d4c1457cfbffffffffffff; maxExpArray[ 78] = 0x0415bc6d6fb7dd71af2cb3ffffffffffff; maxExpArray[ 79] = 0x03eab73b3bbfe282243ce1ffffffffffff; maxExpArray[ 80] = 0x03c1771ac9fb6b4c18e229ffffffffffff; maxExpArray[ 81] = 0x0399e96897690418f785257fffffffffff; maxExpArray[ 82] = 0x0373fc456c53bb779bf0ea9fffffffffff; maxExpArray[ 83] = 0x034f9e8e490c48e67e6ab8bfffffffffff; maxExpArray[ 84] = 0x032cbfd4a7adc790560b3337ffffffffff; maxExpArray[ 85] = 0x030b50570f6e5d2acca94613ffffffffff; maxExpArray[ 86] = 0x02eb40f9f620fda6b56c2861ffffffffff; maxExpArray[ 87] = 0x02cc8340ecb0d0f520a6af58ffffffffff; maxExpArray[ 88] = 0x02af09481380a0a35cf1ba02ffffffffff; maxExpArray[ 89] = 0x0292c5bdd3b92ec810287b1b3fffffffff; maxExpArray[ 90] = 0x0277abdcdab07d5a77ac6d6b9fffffffff; maxExpArray[ 91] = 0x025daf6654b1eaa55fd64df5efffffffff; maxExpArray[ 92] = 0x0244c49c648baa98192dce88b7ffffffff; maxExpArray[ 93] = 0x022ce03cd5619a311b2471268bffffffff; maxExpArray[ 94] = 0x0215f77c045fbe885654a44a0fffffffff; maxExpArray[ 95] = 0x01ffffffffffffffffffffffffffffffff; maxExpArray[ 96] = 0x01eaefdbdaaee7421fc4d3ede5ffffffff; maxExpArray[ 97] = 0x01d6bd8b2eb257df7e8ca57b09bfffffff; maxExpArray[ 98] = 0x01c35fedd14b861eb0443f7f133fffffff; maxExpArray[ 99] = 0x01b0ce43b322bcde4a56e8ada5afffffff; maxExpArray[100] = 0x019f0028ec1fff007f5a195a39dfffffff; maxExpArray[101] = 0x018ded91f0e72ee74f49b15ba527ffffff; maxExpArray[102] = 0x017d8ec7f04136f4e5615fd41a63ffffff; maxExpArray[103] = 0x016ddc6556cdb84bdc8d12d22e6fffffff; maxExpArray[104] = 0x015ecf52776a1155b5bd8395814f7fffff; maxExpArray[105] = 0x015060c256cb23b3b3cc3754cf40ffffff; maxExpArray[106] = 0x01428a2f98d728ae223ddab715be3fffff; maxExpArray[107] = 0x013545598e5c23276ccf0ede68034fffff; maxExpArray[108] = 0x01288c4161ce1d6f54b7f61081194fffff; maxExpArray[109] = 0x011c592761c666aa641d5a01a40f17ffff; maxExpArray[110] = 0x0110a688680a7530515f3e6e6cfdcdffff; maxExpArray[111] = 0x01056f1b5bedf75c6bcb2ce8aed428ffff; maxExpArray[112] = 0x00faadceceeff8a0890f3875f008277fff; maxExpArray[113] = 0x00f05dc6b27edad306388a600f6ba0bfff; maxExpArray[114] = 0x00e67a5a25da41063de1495d5b18cdbfff; maxExpArray[115] = 0x00dcff115b14eedde6fc3aa5353f2e4fff; maxExpArray[116] = 0x00d3e7a3924312399f9aae2e0f868f8fff; maxExpArray[117] = 0x00cb2ff529eb71e41582cccd5a1ee26fff; maxExpArray[118] = 0x00c2d415c3db974ab32a51840c0b67edff; maxExpArray[119] = 0x00bad03e7d883f69ad5b0a186184e06bff; maxExpArray[120] = 0x00b320d03b2c343d4829abd6075f0cc5ff; maxExpArray[121] = 0x00abc25204e02828d73c6e80bcdb1a95bf; maxExpArray[122] = 0x00a4b16f74ee4bb2040a1ec6c15fbbf2df; maxExpArray[123] = 0x009deaf736ac1f569deb1b5ae3f36c130f; maxExpArray[124] = 0x00976bd9952c7aa957f5937d790ef65037; maxExpArray[125] = 0x009131271922eaa6064b73a22d0bd4f2bf; maxExpArray[126] = 0x008b380f3558668c46c91c49a2f8e967b9; maxExpArray[127] = 0x00857ddf0117efa215952912839f6473e6; } /** @dev given a token supply, connector balance, weight and a deposit amount (in the connector token), calculates the return for a given conversion (in the main token) Formula: Return = _supply * ((1 + _depositAmount / _connectorBalance) ^ (_connectorWeight / 1000000) - 1) @param _supply token total supply @param _connectorBalance total connector balance @param _connectorWeight connector weight, represented in ppm, 1-1000000 @param _depositAmount deposit amount, in connector token @return purchase return amount */ function calculatePurchaseReturn(uint256 _supply, uint256 _connectorBalance, uint32 _connectorWeight, uint256 _depositAmount) public view override returns (uint256) { // validate input require(_supply > 0 && _connectorBalance > 0 && _connectorWeight > 0 && _connectorWeight <= MAX_WEIGHT); // special case for 0 deposit amount if (_depositAmount == 0) return 0; // special case if the weight = 100% if (_connectorWeight == MAX_WEIGHT) return _supply.mul(_depositAmount) / _connectorBalance; uint256 result; uint8 precision; uint256 baseN = _depositAmount.add(_connectorBalance); (result, precision) = power(baseN, _connectorBalance, _connectorWeight, MAX_WEIGHT); uint256 temp = _supply.mul(result) >> precision; return temp - _supply; } /** @dev given a token supply, connector balance, weight and a sell amount (in the main token), calculates the return for a given conversion (in the connector token) Formula: Return = _connectorBalance * (1 - (1 - _sellAmount / _supply) ^ (1 / (_connectorWeight / 1000000))) @param _supply token total supply @param _connectorBalance total connector @param _connectorWeight constant connector Weight, represented in ppm, 1-1000000 @param _sellAmount sell amount, in the token itself @return sale return amount */ function calculateSaleReturn(uint256 _supply, uint256 _connectorBalance, uint32 _connectorWeight, uint256 _sellAmount) public view override returns (uint256) { // validate input require(_supply > 0 && _connectorBalance > 0 && _connectorWeight > 0 && _connectorWeight <= MAX_WEIGHT && _sellAmount <= _supply); // special case for 0 sell amount if (_sellAmount == 0) return 0; // special case for selling the entire supply if (_sellAmount == _supply) return _connectorBalance; // special case if the weight = 100% if (_connectorWeight == MAX_WEIGHT) return _connectorBalance.mul(_sellAmount) / _supply; uint256 result; uint8 precision; uint256 baseD = _supply - _sellAmount; (result, precision) = power(_supply, baseD, MAX_WEIGHT, _connectorWeight); uint256 temp1 = _connectorBalance.mul(result); uint256 temp2 = _connectorBalance << precision; return (temp1 - temp2) / result; } /** @dev given two connector balances/weights and a sell amount (in the first connector token), calculates the return for a conversion from the first connector token to the second connector token (in the second connector token) Formula: Return = _toConnectorBalance * (1 - (_fromConnectorBalance / (_fromConnectorBalance + _amount)) ^ (_fromConnectorWeight / _toConnectorWeight)) @param _fromConnectorBalance input connector balance @param _fromConnectorWeight input connector weight, represented in ppm, 1-1000000 @param _toConnectorBalance output connector balance @param _toConnectorWeight output connector weight, represented in ppm, 1-1000000 @param _amount input connector amount @return second connector amount */ function calculateCrossConnectorReturn(uint256 _fromConnectorBalance, uint32 _fromConnectorWeight, uint256 _toConnectorBalance, uint32 _toConnectorWeight, uint256 _amount) public view override returns (uint256) { // validate input require(_fromConnectorBalance > 0 && _fromConnectorWeight > 0 && _fromConnectorWeight <= MAX_WEIGHT && _toConnectorBalance > 0 && _toConnectorWeight > 0 && _toConnectorWeight <= MAX_WEIGHT); // special case for equal weights if (_fromConnectorWeight == _toConnectorWeight) return _toConnectorBalance.mul(_amount) / _fromConnectorBalance.add(_amount); uint256 result; uint8 precision; uint256 baseN = _fromConnectorBalance.add(_amount); (result, precision) = power(baseN, _fromConnectorBalance, _fromConnectorWeight, _toConnectorWeight); uint256 temp1 = _toConnectorBalance.mul(result); uint256 temp2 = _toConnectorBalance << precision; return (temp1 - temp2) / result; } /** General Description: Determine a value of precision. Calculate an integer approximation of (_baseN / _baseD) ^ (_expN / _expD) * 2 ^ precision. Return the result along with the precision used. Detailed Description: Instead of calculating "base ^ exp", we calculate "e ^ (log(base) * exp)". The value of "log(base)" is represented with an integer slightly smaller than "log(base) * 2 ^ precision". The larger "precision" is, the more accurately this value represents the real value. However, the larger "precision" is, the more bits are required in order to store this value. And the exponentiation function, which takes "x" and calculates "e ^ x", is limited to a maximum exponent (maximum value of "x"). This maximum exponent depends on the "precision" used, and it is given by "maxExpArray[precision] >> (MAX_PRECISION - precision)". Hence we need to determine the highest precision which can be used for the given input, before calling the exponentiation function. This allows us to compute "base ^ exp" with maximum accuracy and without exceeding 256 bits in any of the intermediate computations. This functions assumes that "_expN < 2 ^ 256 / log(MAX_NUM - 1)", otherwise the multiplication should be replaced with a "safeMul". */ function power(uint256 _baseN, uint256 _baseD, uint32 _expN, uint32 _expD) internal view returns (uint256, uint8) { require(_baseN < MAX_NUM); uint256 baseLog; uint256 base = _baseN * FIXED_1 / _baseD; if (base < OPT_LOG_MAX_VAL) { baseLog = optimalLog(base); } else { baseLog = generalLog(base); } uint256 baseLogTimesExp = baseLog * _expN / _expD; if (baseLogTimesExp < OPT_EXP_MAX_VAL) { return (optimalExp(baseLogTimesExp), MAX_PRECISION); } else { uint8 precision = findPositionInMaxExpArray(baseLogTimesExp); return (generalExp(baseLogTimesExp >> (MAX_PRECISION - precision), precision), precision); } } /** Compute log(x / FIXED_1) * FIXED_1. This functions assumes that "x >= FIXED_1", because the output would be negative otherwise. */ function generalLog(uint256 x) internal pure returns (uint256) { uint256 res = 0; // If x >= 2, then we compute the integer part of log2(x), which is larger than 0. if (x >= FIXED_2) { uint8 count = floorLog2(x / FIXED_1); x >>= count; // now x < 2 res = count * FIXED_1; } // If x > 1, then we compute the fraction part of log2(x), which is larger than 0. if (x > FIXED_1) { for (uint8 i = MAX_PRECISION; i > 0; --i) { x = (x * x) / FIXED_1; // now 1 < x < 4 if (x >= FIXED_2) { x >>= 1; // now 1 < x < 2 res += ONE << (i - 1); } } } return res * LN2_NUMERATOR / LN2_DENOMINATOR; } /** Compute the largest integer smaller than or equal to the binary logarithm of the input. */ function floorLog2(uint256 _n) internal pure returns (uint8) { uint8 res = 0; if (_n < 256) { // At most 8 iterations while (_n > 1) { _n >>= 1; res += 1; } } else { // Exactly 8 iterations for (uint8 s = 128; s > 0; s >>= 1) { if (_n >= (ONE << s)) { _n >>= s; res |= s; } } } return res; } /** The global "maxExpArray" is sorted in descending order, and therefore the following statements are equivalent: - This function finds the position of [the smallest value in "maxExpArray" larger than or equal to "x"] - This function finds the highest position of [a value in "maxExpArray" larger than or equal to "x"] */ function findPositionInMaxExpArray(uint256 _x) internal view returns (uint8) { uint8 lo = MIN_PRECISION; uint8 hi = MAX_PRECISION; while (lo + 1 < hi) { uint8 mid = (lo + hi) / 2; if (maxExpArray[mid] >= _x) lo = mid; else hi = mid; } if (maxExpArray[hi] >= _x) return hi; if (maxExpArray[lo] >= _x) return lo; require(false); return 0; } /** This function can be auto-generated by the script 'PrintFunctionGeneralExp.py'. It approximates "e ^ x" via maclaurin summation: "(x^0)/0! + (x^1)/1! + ... + (x^n)/n!". It returns "e ^ (x / 2 ^ precision) * 2 ^ precision", that is, the result is upshifted for accuracy. The global "maxExpArray" maps each "precision" to "((maximumExponent + 1) << (MAX_PRECISION - precision)) - 1". The maximum permitted value for "x" is therefore given by "maxExpArray[precision] >> (MAX_PRECISION - precision)". */ function generalExp(uint256 _x, uint8 _precision) internal pure returns (uint256) { uint256 xi = _x; uint256 res = 0; xi = (xi * _x) >> _precision; res += xi * 0x3442c4e6074a82f1797f72ac0000000; // add x^02 * (33! / 02!) xi = (xi * _x) >> _precision; res += xi * 0x116b96f757c380fb287fd0e40000000; // add x^03 * (33! / 03!) xi = (xi * _x) >> _precision; res += xi * 0x045ae5bdd5f0e03eca1ff4390000000; // add x^04 * (33! / 04!) xi = (xi * _x) >> _precision; res += xi * 0x00defabf91302cd95b9ffda50000000; // add x^05 * (33! / 05!) xi = (xi * _x) >> _precision; res += xi * 0x002529ca9832b22439efff9b8000000; // add x^06 * (33! / 06!) xi = (xi * _x) >> _precision; res += xi * 0x00054f1cf12bd04e516b6da88000000; // add x^07 * (33! / 07!) xi = (xi * _x) >> _precision; res += xi * 0x0000a9e39e257a09ca2d6db51000000; // add x^08 * (33! / 08!) xi = (xi * _x) >> _precision; res += xi * 0x000012e066e7b839fa050c309000000; // add x^09 * (33! / 09!) xi = (xi * _x) >> _precision; res += xi * 0x000001e33d7d926c329a1ad1a800000; // add x^10 * (33! / 10!) xi = (xi * _x) >> _precision; res += xi * 0x0000002bee513bdb4a6b19b5f800000; // add x^11 * (33! / 11!) xi = (xi * _x) >> _precision; res += xi * 0x00000003a9316fa79b88eccf2a00000; // add x^12 * (33! / 12!) xi = (xi * _x) >> _precision; res += xi * 0x0000000048177ebe1fa812375200000; // add x^13 * (33! / 13!) xi = (xi * _x) >> _precision; res += xi * 0x0000000005263fe90242dcbacf00000; // add x^14 * (33! / 14!) xi = (xi * _x) >> _precision; res += xi * 0x000000000057e22099c030d94100000; // add x^15 * (33! / 15!) xi = (xi * _x) >> _precision; res += xi * 0x0000000000057e22099c030d9410000; // add x^16 * (33! / 16!) xi = (xi * _x) >> _precision; res += xi * 0x00000000000052b6b54569976310000; // add x^17 * (33! / 17!) xi = (xi * _x) >> _precision; res += xi * 0x00000000000004985f67696bf748000; // add x^18 * (33! / 18!) xi = (xi * _x) >> _precision; res += xi * 0x000000000000003dea12ea99e498000; // add x^19 * (33! / 19!) xi = (xi * _x) >> _precision; res += xi * 0x00000000000000031880f2214b6e000; // add x^20 * (33! / 20!) xi = (xi * _x) >> _precision; res += xi * 0x000000000000000025bcff56eb36000; // add x^21 * (33! / 21!) xi = (xi * _x) >> _precision; res += xi * 0x000000000000000001b722e10ab1000; // add x^22 * (33! / 22!) xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000001317c70077000; // add x^23 * (33! / 23!) xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000cba84aafa00; // add x^24 * (33! / 24!) xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000082573a0a00; // add x^25 * (33! / 25!) xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000005035ad900; // add x^26 * (33! / 26!) xi = (xi * _x) >> _precision; res += xi * 0x000000000000000000000002f881b00; // add x^27 * (33! / 27!) xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000001b29340; // add x^28 * (33! / 28!) xi = (xi * _x) >> _precision; res += xi * 0x00000000000000000000000000efc40; // add x^29 * (33! / 29!) xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000007fe0; // add x^30 * (33! / 30!) xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000420; // add x^31 * (33! / 31!) xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000021; // add x^32 * (33! / 32!) xi = (xi * _x) >> _precision; res += xi * 0x0000000000000000000000000000001; // add x^33 * (33! / 33!) return res / 0x688589cc0e9505e2f2fee5580000000 + _x + (ONE << _precision); // divide by 33! and then add x^1 / 1! + x^0 / 0! } /** Return log(x / FIXED_1) * FIXED_1 Input range: FIXED_1 <= x <= LOG_EXP_MAX_VAL - 1 Auto-generated via 'PrintFunctionOptimalLog.py' Detailed description: - Rewrite the input as a product of natural exponents and a single residual r, such that 1 < r < 2 - The natural logarithm of each (pre-calculated) exponent is the degree of the exponent - The natural logarithm of r is calculated via Taylor series for log(1 + x), where x = r - 1 - The natural logarithm of the input is calculated by summing up the intermediate results above - For example: log(250) = log(e^4 * e^1 * e^0.5 * 1.021692859) = 4 + 1 + 0.5 + log(1 + 0.021692859) */ function optimalLog(uint256 x) internal pure returns (uint256) { uint256 res = 0; uint256 y; uint256 z; uint256 w; if (x >= 0xd3094c70f034de4b96ff7d5b6f99fcd8) {res += 0x40000000000000000000000000000000; x = x * FIXED_1 / 0xd3094c70f034de4b96ff7d5b6f99fcd8;} // add 1 / 2^1 if (x >= 0xa45af1e1f40c333b3de1db4dd55f29a7) {res += 0x20000000000000000000000000000000; x = x * FIXED_1 / 0xa45af1e1f40c333b3de1db4dd55f29a7;} // add 1 / 2^2 if (x >= 0x910b022db7ae67ce76b441c27035c6a1) {res += 0x10000000000000000000000000000000; x = x * FIXED_1 / 0x910b022db7ae67ce76b441c27035c6a1;} // add 1 / 2^3 if (x >= 0x88415abbe9a76bead8d00cf112e4d4a8) {res += 0x08000000000000000000000000000000; x = x * FIXED_1 / 0x88415abbe9a76bead8d00cf112e4d4a8;} // add 1 / 2^4 if (x >= 0x84102b00893f64c705e841d5d4064bd3) {res += 0x04000000000000000000000000000000; x = x * FIXED_1 / 0x84102b00893f64c705e841d5d4064bd3;} // add 1 / 2^5 if (x >= 0x8204055aaef1c8bd5c3259f4822735a2) {res += 0x02000000000000000000000000000000; x = x * FIXED_1 / 0x8204055aaef1c8bd5c3259f4822735a2;} // add 1 / 2^6 if (x >= 0x810100ab00222d861931c15e39b44e99) {res += 0x01000000000000000000000000000000; x = x * FIXED_1 / 0x810100ab00222d861931c15e39b44e99;} // add 1 / 2^7 if (x >= 0x808040155aabbbe9451521693554f733) {res += 0x00800000000000000000000000000000; x = x * FIXED_1 / 0x808040155aabbbe9451521693554f733;} // add 1 / 2^8 z = y = x - FIXED_1; w = y * y / FIXED_1; res += z * (0x100000000000000000000000000000000 - y) / 0x100000000000000000000000000000000; z = z * w / FIXED_1; // add y^01 / 01 - y^02 / 02 res += z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y) / 0x200000000000000000000000000000000; z = z * w / FIXED_1; // add y^03 / 03 - y^04 / 04 res += z * (0x099999999999999999999999999999999 - y) / 0x300000000000000000000000000000000; z = z * w / FIXED_1; // add y^05 / 05 - y^06 / 06 res += z * (0x092492492492492492492492492492492 - y) / 0x400000000000000000000000000000000; z = z * w / FIXED_1; // add y^07 / 07 - y^08 / 08 res += z * (0x08e38e38e38e38e38e38e38e38e38e38e - y) / 0x500000000000000000000000000000000; z = z * w / FIXED_1; // add y^09 / 09 - y^10 / 10 res += z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y) / 0x600000000000000000000000000000000; z = z * w / FIXED_1; // add y^11 / 11 - y^12 / 12 res += z * (0x089d89d89d89d89d89d89d89d89d89d89 - y) / 0x700000000000000000000000000000000; z = z * w / FIXED_1; // add y^13 / 13 - y^14 / 14 res += z * (0x088888888888888888888888888888888 - y) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16 return res; } /** Return e ^ (x / FIXED_1) * FIXED_1 Input range: 0 <= x <= OPT_EXP_MAX_VAL - 1 Auto-generated via 'PrintFunctionOptimalExp.py' Detailed description: - Rewrite the input as a sum of binary exponents and a single residual r, as small as possible - The exponentiation of each binary exponent is given (pre-calculated) - The exponentiation of r is calculated via Taylor series for e^x, where x = r - The exponentiation of the input is calculated by multiplying the intermediate results above - For example: e^5.521692859 = e^(4 + 1 + 0.5 + 0.021692859) = e^4 * e^1 * e^0.5 * e^0.021692859 */ function optimalExp(uint256 x) internal pure returns (uint256) { uint256 res = 0; uint256 y; uint256 z; z = y = x % 0x10000000000000000000000000000000; // get the input modulo 2^(-3) z = z * y / FIXED_1; res += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!) z = z * y / FIXED_1; res += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!) z = z * y / FIXED_1; res += z * 0x0168244fdac78000; // add y^04 * (20! / 04!) z = z * y / FIXED_1; res += z * 0x004807432bc18000; // add y^05 * (20! / 05!) z = z * y / FIXED_1; res += z * 0x000c0135dca04000; // add y^06 * (20! / 06!) z = z * y / FIXED_1; res += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!) z = z * y / FIXED_1; res += z * 0x000036e0f639b800; // add y^08 * (20! / 08!) z = z * y / FIXED_1; res += z * 0x00000618fee9f800; // add y^09 * (20! / 09!) z = z * y / FIXED_1; res += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!) z = z * y / FIXED_1; res += z * 0x0000000e30dce400; // add y^11 * (20! / 11!) z = z * y / FIXED_1; res += z * 0x000000012ebd1300; // add y^12 * (20! / 12!) z = z * y / FIXED_1; res += z * 0x0000000017499f00; // add y^13 * (20! / 13!) z = z * y / FIXED_1; res += z * 0x0000000001a9d480; // add y^14 * (20! / 14!) z = z * y / FIXED_1; res += z * 0x00000000001c6380; // add y^15 * (20! / 15!) z = z * y / FIXED_1; res += z * 0x000000000001c638; // add y^16 * (20! / 16!) z = z * y / FIXED_1; res += z * 0x0000000000001ab8; // add y^17 * (20! / 17!) z = z * y / FIXED_1; res += z * 0x000000000000017c; // add y^18 * (20! / 18!) z = z * y / FIXED_1; res += z * 0x0000000000000014; // add y^19 * (20! / 19!) z = z * y / FIXED_1; res += z * 0x0000000000000001; // add y^20 * (20! / 20!) res = res / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0! if ((x & 0x010000000000000000000000000000000) != 0) res = res * 0x1c3d6a24ed82218787d624d3e5eba95f9 / 0x18ebef9eac820ae8682b9793ac6d1e776; // multiply by e^2^(-3) if ((x & 0x020000000000000000000000000000000) != 0) res = res * 0x18ebef9eac820ae8682b9793ac6d1e778 / 0x1368b2fc6f9609fe7aceb46aa619baed4; // multiply by e^2^(-2) if ((x & 0x040000000000000000000000000000000) != 0) res = res * 0x1368b2fc6f9609fe7aceb46aa619baed5 / 0x0bc5ab1b16779be3575bd8f0520a9f21f; // multiply by e^2^(-1) if ((x & 0x080000000000000000000000000000000) != 0) res = res * 0x0bc5ab1b16779be3575bd8f0520a9f21e / 0x0454aaa8efe072e7f6ddbab84b40a55c9; // multiply by e^2^(+0) if ((x & 0x100000000000000000000000000000000) != 0) res = res * 0x0454aaa8efe072e7f6ddbab84b40a55c5 / 0x00960aadc109e7a3bf4578099615711ea; // multiply by e^2^(+1) if ((x & 0x200000000000000000000000000000000) != 0) res = res * 0x00960aadc109e7a3bf4578099615711d7 / 0x0002bf84208204f5977f9a8cf01fdce3d; // multiply by e^2^(+2) if ((x & 0x400000000000000000000000000000000) != 0) res = res * 0x0002bf84208204f5977f9a8cf01fdc307 / 0x0000003c6ab775dd0b95b4cbee7e65d11; // multiply by e^2^(+3) return res; } }
pragma solidity ^0.6.0; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; //////////////////////////////////////////////////////////////////////////////////////////// /// @title RewardToken /// @author Christopher Dixon //////////////////////////////////////////////////////////////////////////////////////////// contract RewardToken is Ownable, ERC20 { ///@notice constructor sets up token names and symbols for the RewardToken constructor( string memory _tokenName, string memory _tokenSymbol ) public ERC20(_tokenSymbol, _tokenName) { mint(0x77A9d21bEf6a21a045503df0d8D58678392BAFa5, 81688155000000000000000000);//mint deploying address the initial supply of tokens } /** @notice mint is an only owner function that allows the owner to mint new tokens to an input account @param _to is the address that will receive the new tokens @param _amount is the amount of token they will receive **/ function mint(address _to, uint256 _amount) public onlyOwner { _mint(_to, _amount); } /** @notice burn is an only owner function that allows the owner to burn tokens from an input account @param _from is the address where the tokens will be burnt @param _amount is the amount of token to be burnt **/ function burn(address _from, uint256 _amount) public onlyOwner { _burn(_from, _amount); } }
pragma solidity ^0.6.0; /* Bancor Formula interface */ abstract contract IBancorFormula { function calculatePurchaseReturn(uint256 _supply, uint256 _connectorBalance, uint32 _connectorWeight, uint256 _depositAmount) public view virtual returns (uint256); function calculateSaleReturn(uint256 _supply, uint256 _connectorBalance, uint32 _connectorWeight, uint256 _sellAmount) public view virtual returns (uint256); function calculateCrossConnectorReturn(uint256 _fromConnectorBalance, uint32 _fromConnectorWeight, uint256 _toConnectorBalance, uint32 _toConnectorWeight, uint256 _amount) public view virtual returns (uint256); }
pragma solidity ^0.6.0; abstract contract IFundraisingController { function openTrading() external virtual; function updateTappedAmount(address _token) external virtual; function collateralsToBeClaimed(address _collateral) public view virtual returns (uint256); function balanceOf(address _who, address _token) public view virtual returns (uint256); }
pragma solidity ^0.6.0; abstract contract ITap { function updateBeneficiary(address _beneficiary) external virtual; function updateMaximumTapRateIncreasePct(uint256 _maximumTapRateIncreasePct) external virtual; function updateMaximumTapFloorDecreasePct(uint256 _maximumTapFloorDecreasePct) external virtual; function addTappedToken(address _token, uint256 _rate, uint256 _floor) external virtual; function updateTappedToken(address _token, uint256 _rate, uint256 _floor) external virtual; function resetTappedToken(address _token) external virtual; function updateTappedAmount(address _token) external virtual; function withdraw(address _token, uint _amount) external virtual; function getMaximumWithdrawal(address _token) public view virtual returns (uint256); function getRates(address _token) public view virtual returns (uint256); }
pragma solidity ^0.6.0; /* Utilities & Common Modifiers */ contract Utils { /** constructor */ constructor() public { } // verifies that an amount is greater than zero modifier greaterThanZero(uint256 _amount) { require(_amount > 0); _; } // validates an address - currently only checks that it isn't null modifier validAddress(address _address) { require(_address != address(0)); _; } // verifies that the address is different than this contract address modifier notThis(address _address) { require(_address != address(this)); _; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /* * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with GSN meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; } function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "../GSN/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor () internal { address msgSender = _msgSender(); _owner = msgSender; emit OwnershipTransferred(address(0), msgSender); } /** * @dev Returns the address of the current owner. */ function owner() public view returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(_owner == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @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) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @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 sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @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) { // 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 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts 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) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts 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) { require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts 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 mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message 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, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; import "../../GSN/Context.sol"; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * For a generic mechanism see {ERC20PresetMinterPauser}. * * TIP: For a detailed writeup see our guide * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * We have followed general OpenZeppelin guidelines: functions revert instead * of returning `false` on failure. This behavior is nonetheless conventional * and does not conflict with the expectations of ERC20 applications. * * Additionally, an {Approval} event is emitted on calls to {transferFrom}. * This allows applications to reconstruct the allowance for all accounts just * by listening to said events. Other implementations of the EIP may not emit * these events, as it isn't required by the specification. * * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} * functions have been added to mitigate the well-known issues around setting * allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256; using Address for address; mapping (address => uint256) private _balances; mapping (address => mapping (address => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for {name} and {symbol}, initializes {decimals} with * a default value of 18. * * To select a different value for {decimals}, use {_setupDecimals}. * * All three of these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol) public { _name = name; _symbol = symbol; _decimals = 18; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the value {ERC20} uses, unless {_setupDecimals} is * called. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view override returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view override returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `recipient` cannot be the zero address. * - the caller must have a balance of at least `amount`. */ function transfer(address recipient, uint256 amount) public virtual override returns (bool) { _transfer(_msgSender(), recipient, amount); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual override returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 amount) public virtual override returns (bool) { _approve(_msgSender(), spender, amount); return true; } /** * @dev See {IERC20-transferFrom}. * * Emits an {Approval} event indicating the updated allowance. This is not * required by the EIP. See the note at the beginning of {ERC20}; * * Requirements: * - `sender` and `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. * - the caller must have allowance for ``sender``'s tokens of at least * `amount`. */ function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) { _transfer(sender, recipient, amount); _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance")); return true; } /** * @dev Atomically increases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. */ function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue)); return true; } /** * @dev Atomically decreases the allowance granted to `spender` by the caller. * * This is an alternative to {approve} that can be used as a mitigation for * problems described in {IERC20-approve}. * * Emits an {Approval} event indicating the updated allowance. * * Requirements: * * - `spender` cannot be the zero address. * - `spender` must have allowance for the caller of at least * `subtractedValue`. */ function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) { _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero")); return true; } /** * @dev Moves tokens `amount` from `sender` to `recipient`. * * This is internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * Requirements: * * - `sender` cannot be the zero address. * - `recipient` cannot be the zero address. * - `sender` must have a balance of at least `amount`. */ function _transfer(address sender, address recipient, uint256 amount) internal virtual { require(sender != address(0), "ERC20: transfer from the zero address"); require(recipient != address(0), "ERC20: transfer to the zero address"); _beforeTokenTransfer(sender, recipient, amount); _balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); } /** @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. * * Requirements * * - `to` cannot be the zero address. */ function _mint(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: mint to the zero address"); _beforeTokenTransfer(address(0), account, amount); _totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); } /** * @dev Destroys `amount` tokens from `account`, reducing the * total supply. * * Emits a {Transfer} event with `to` set to the zero address. * * Requirements * * - `account` cannot be the zero address. * - `account` must have at least `amount` tokens. */ function _burn(address account, uint256 amount) internal virtual { require(account != address(0), "ERC20: burn from the zero address"); _beforeTokenTransfer(account, address(0), amount); _balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); } /** * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. */ function _approve(address owner, address spender, uint256 amount) internal virtual { require(owner != address(0), "ERC20: approve from the zero address"); require(spender != address(0), "ERC20: approve to the zero address"); _allowances[owner][spender] = amount; emit Approval(owner, spender, amount); } /** * @dev Sets {decimals} to a value other than the default one of 18. * * WARNING: This function should only be called from the constructor. Most * applications that interact with token contracts will not expect * {decimals} to ever change, and may work incorrectly if it does. */ function _setupDecimals(uint8 decimals_) internal { _decimals = decimals_; } /** * @dev Hook that is called before any transfer of tokens. This includes * minting and burning. * * Calling conditions: * * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens * will be to transferred to `to`. * - when `from` is zero, `amount` tokens will be minted for `to`. * - when `to` is zero, `amount` of ``from``'s tokens will be burned. * - `from` and `to` are never both zero. * * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. */ function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual { } }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); }
// SPDX-License-Identifier: MIT pragma solidity ^0.6.2; /** * @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 in 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"); return _functionCallWithValue(target, data, value, errorMessage); } function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) { require(isContract(target), "Address: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: weiValue }(data); 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); } } } }
{ "remappings": [], "optimizer": { "enabled": true, "runs": 1 }, "evmVersion": "istanbul", "libraries": { "": {} }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IBancorFormula","name":"_formula","type":"address"},{"internalType":"contract RewardToken","name":"_rewardToken","type":"address"},{"internalType":"contract IERC20","name":"_dai","type":"address"},{"internalType":"address","name":"_dao","type":"address"},{"internalType":"address","name":"_beneficiary","type":"address"},{"internalType":"uint256","name":"_batchBlocks","type":"uint256"},{"internalType":"uint256","name":"_buyFeePct","type":"uint256"},{"internalType":"uint256","name":"_sellFeePct","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"virtualSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"virtualBalance","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"reserveRatio","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"AddCollateralToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"}],"name":"CancelBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimBuyOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"ClaimCancelledBuyOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ClaimCancelledSellOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"ClaimSellOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"supply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balance","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"reserveRatio","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"NewBatch","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"supply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"buyFeePct","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sellFeePct","type":"uint256"},{"indexed":false,"internalType":"address","name":"formula","type":"address"}],"name":"NewMetaBatch","type":"event"},{"anonymous":false,"inputs":[],"name":"Open","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"OpenBuyOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"seller","type":"address"},{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"OpenSellOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateral","type":"address"}],"name":"RemoveCollateralToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"}],"name":"UpdateBeneficiary","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"virtualSupply","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"virtualBalance","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"reserveRatio","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"slippage","type":"uint256"}],"name":"UpdateCollateralToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"buyFeePct","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sellFeePct","type":"uint256"}],"name":"UpdateFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"formula","type":"address"}],"name":"UpdateFormula","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"batchId","type":"uint256"},{"indexed":true,"internalType":"address","name":"collateral","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalBuySpend","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalBuyReturn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSellSpend","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalSellReturn","type":"uint256"}],"name":"UpdatePricing","type":"event"},{"anonymous":false,"inputs":[],"name":"paused","type":"event"},{"inputs":[],"name":"DAI","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PCT_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PPM","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_virtualSupply","type":"uint256"},{"internalType":"uint256","name":"_virtualBalance","type":"uint256"},{"internalType":"uint32","name":"_reserveRatio","type":"uint32"},{"internalType":"uint256","name":"_slippage","type":"uint256"}],"name":"addCollateralToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"batchBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"buyFeePct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"uint256","name":"_batchId","type":"uint256"},{"internalType":"address","name":"_collateral","type":"address"}],"name":"claimBuyOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"uint256","name":"_batchId","type":"uint256"},{"internalType":"address","name":"_collateral","type":"address"}],"name":"claimCancelledBuyOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_seller","type":"address"},{"internalType":"uint256","name":"_batchId","type":"uint256"},{"internalType":"address","name":"_collateral","type":"address"}],"name":"claimCancelledSellOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_seller","type":"address"},{"internalType":"uint256","name":"_batchId","type":"uint256"},{"internalType":"address","name":"_collateral","type":"address"}],"name":"claimSellOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collaterals","outputs":[{"internalType":"bool","name":"whitelisted","type":"bool"},{"internalType":"uint256","name":"virtualSupply","type":"uint256"},{"internalType":"uint256","name":"virtualBalance","type":"uint256"},{"internalType":"uint32","name":"reserveRatio","type":"uint32"},{"internalType":"uint256","name":"slippage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"collateralsToBeClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"controller","outputs":[{"internalType":"contract IFundraisingController","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dao","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"formula","outputs":[{"internalType":"contract IBancorFormula","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_batchId","type":"uint256"},{"internalType":"address","name":"_collateral","type":"address"}],"name":"getBatch","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"}],"name":"getCollateralToken","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentBatchId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_supply","type":"uint256"},{"internalType":"uint256","name":"_balance","type":"uint256"},{"internalType":"uint32","name":"_reserveRatio","type":"uint32"}],"name":"getStaticPricePPM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"isOpen","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"metaBatches","outputs":[{"internalType":"bool","name":"initialized","type":"bool"},{"internalType":"uint256","name":"realSupply","type":"uint256"},{"internalType":"uint256","name":"buyFeePct","type":"uint256"},{"internalType":"uint256","name":"sellFeePct","type":"uint256"},{"internalType":"contract IBancorFormula","name":"formula","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_buyer","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"openBuyOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_seller","type":"address"},{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"openSellOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"}],"name":"removeCollateralToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"contract RewardToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sellFeePct","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IFundraisingController","name":"_controller","type":"address"},{"internalType":"contract ITap","name":"_tap","type":"address"}],"name":"setUpMarket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tap","outputs":[{"internalType":"contract ITap","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokensToBeMinted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralToken","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_beneficiary","type":"address"}],"name":"updateBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateral","type":"address"},{"internalType":"uint256","name":"_virtualSupply","type":"uint256"},{"internalType":"uint256","name":"_virtualBalance","type":"uint256"},{"internalType":"uint32","name":"_reserveRatio","type":"uint32"},{"internalType":"uint256","name":"_slippage","type":"uint256"}],"name":"updateCollateralToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_buyFeePct","type":"uint256"},{"internalType":"uint256","name":"_sellFeePct","type":"uint256"}],"name":"updateFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IBancorFormula","name":"_formula","type":"address"}],"name":"updateFormula","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b5060405162003a6238038062003a6283398181016040526101008110156200003857600080fd5b508051602082015160408301516060840151608085015160a086015160c087015160e0909701519596949593949293919290916000620000806001600160e01b03620001fa16565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a350600083116200010b5760405162461bcd60e51b815260040180806020018281038252602581526020018062003a3d6025913960400191505060405180910390fd5b6200011f826001600160e01b03620001fe16565b80156200013b57506200013b816001600160e01b03620001fe16565b6200018d576040805162461bcd60e51b815260206004820152601660248201527f496e76616c6964204665652050657263656e7461676500000000000000000000604482015290519081900360640190fd5b600380546001600160a01b03199081166001600160a01b03998a1617909155600580548216998916999099179098556004805489169488169490941790935560079190915560085560095560068054851692841692909217909155600c805490931691161790556200020b565b3390565b670de0b6b3a76400001190565b613822806200021b6000396000f3fe6080604052600436106101c05760003560e01c80630aaffd2a146101c55780630d720bbc146101fa5780630f1ff5ea14610228578063177c14991461026b57806338af3eed146102cb5780633fae9bfb146102fc5780634162169f1461033257806347535d7b146103475780634afe6c47146103705780634b75f54f146103b55780635e6f6c77146103ca578063683dee471461040d5780636db794371461049d578063715018a6146104cd57806378aada53146104e257806378ea61031461051d5780637b9e86bf146105605780637cfab0cb146105755780638456cb59146105b15780638a9b1e2d146105c65780638da5cb5b146106175780639249be281461062c57806394f9059f1461066f5780639ba9dada146106a2578063a9059cbb146106b7578063c56f0f6c146106f0578063d5b49a7114610705578063dbbdf2fe14610738578063e0bab4c41461077b578063e720ac8e14610790578063eeb97d3b146107a5578063f190e4271461080b578063f2fde38b1461083e578063f77c479114610871578063f79c5c7c14610886578063f7c618c11461089b578063fc157cb4146108b0578063fd221031146108c5578063fd531e03146108da575b600080fd5b3480156101d157600080fd5b506101f8600480360360208110156101e857600080fd5b50356001600160a01b031661092b565b005b34801561020657600080fd5b5061020f6109e7565b6040805163ffffffff9092168252519081900360200190f35b34801561023457600080fd5b506101f86004803603606081101561024b57600080fd5b506001600160a01b038135811691602081013590911690604001356109ee565b34801561027757600080fd5b506102956004803603602081101561028e57600080fd5b5035610b9c565b60408051951515865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190f35b3480156102d757600080fd5b506102e0610bd8565b604080516001600160a01b039092168252519081900360200190f35b6101f86004803603606081101561031257600080fd5b506001600160a01b03813581169160208101359091169060400135610be7565b34801561033e57600080fd5b506102e0610d82565b34801561035357600080fd5b5061035c610d91565b604080519115158252519081900360200190f35b34801561037c57600080fd5b506103a36004803603602081101561039357600080fd5b50356001600160a01b0316610d9a565b60408051918252519081900360200190f35b3480156103c157600080fd5b506102e0610dac565b3480156103d657600080fd5b506101f8600480360360608110156103ed57600080fd5b506001600160a01b03813581169160208101359160409091013516610dbb565b34801561041957600080fd5b506104466004803603604081101561043057600080fd5b50803590602001356001600160a01b0316610f05565b604080519a15158b5298151560208b015289890197909752606089019590955263ffffffff909316608088015260a087019190915260c086015260e085015261010084015261012083015251908190036101400190f35b3480156104a957600080fd5b506101f8600480360360408110156104c057600080fd5b5080359060200135610f7c565b3480156104d957600080fd5b506101f8611045565b3480156104ee57600080fd5b506101f86004803603604081101561050557600080fd5b506001600160a01b03813581169160200135166110d5565b34801561052957600080fd5b506101f86004803603606081101561054057600080fd5b506001600160a01b03813581169160208101359160409091013516611174565b34801561056c57600080fd5b506103a36112be565b34801561058157600080fd5b506103a36004803603606081101561059857600080fd5b508035906020810135906040013563ffffffff166112c4565b3480156105bd57600080fd5b506101f86112db565b3480156105d257600080fd5b506101f8600480360360a08110156105e957600080fd5b506001600160a01b038135169060208101359060408101359063ffffffff60608201351690608001356113db565b34801561062357600080fd5b506102e06114e1565b34801561063857600080fd5b506101f86004803603606081101561064f57600080fd5b506001600160a01b038135811691602081013591604090910135166114f0565b34801561067b57600080fd5b506101f86004803603602081101561069257600080fd5b50356001600160a01b031661159c565b3480156106ae57600080fd5b506103a3611645565b3480156106c357600080fd5b506101f8600480360360408110156106da57600080fd5b506001600160a01b03813516906020013561164b565b3480156106fc57600080fd5b506103a361172e565b34801561071157600080fd5b506101f86004803603602081101561072857600080fd5b50356001600160a01b0316611734565b34801561074457600080fd5b506101f86004803603606081101561075b57600080fd5b506001600160a01b03813581169160208101359160409091013516611795565b34801561078757600080fd5b506102e061183e565b34801561079c57600080fd5b506103a361184d565b3480156107b157600080fd5b506107d8600480360360208110156107c857600080fd5b50356001600160a01b031661185c565b60408051951515865260208601949094528484019290925263ffffffff1660608401526080830152519081900360a00190f35b34801561081757600080fd5b506107d86004803603602081101561082e57600080fd5b50356001600160a01b0316611895565b34801561084a57600080fd5b506101f86004803603602081101561086157600080fd5b50356001600160a01b03166118d8565b34801561087d57600080fd5b506102e06119be565b34801561089257600080fd5b506103a36119cd565b3480156108a757600080fd5b506102e06119d3565b3480156108bc57600080fd5b506103a36119e2565b3480156108d157600080fd5b506102e06119ee565b3480156108e657600080fd5b506101f8600480360360a08110156108fd57600080fd5b506001600160a01b038135169060208101359060408101359063ffffffff60608201351690608001356119fd565b610933611b0e565b6000546001600160a01b03908116911614610983576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b61098c81611b12565b6109db576040805162461bcd60e51b815260206004820152601b60248201527a496e76616c69642042656e6566696369617279204164647265737360281b604482015290519081900360640190fd5b6109e481611b24565b50565b620f424081565b6109f6611b0e565b6000546001600160a01b03908116911614610a46576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600a5460ff16610a8b576040805162461bcd60e51b815260206004820152600b60248201526a24b9903737ba1037b832b760a91b604482015290519081900360640190fd5b610a9482611b6e565b610ae5576040805162461bcd60e51b815260206004820152601d60248201527f436f6c6c61746572616c206973206e6f742057686974656c6973746564000000604482015290519081900360640190fd5b610af6610af0611b8c565b83611bb2565b15610b3b576040805162461bcd60e51b815260206004820152601060248201526f10985d18da081a5cc818d85b98db195960821b604482015290519081900360640190fd5b610b458382611be7565b610b8c576040805162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189bdb9908185b5bdd5b9d606a1b604482015290519081900360640190fd5b610b97838383611c78565b505050565b600f602052600090815260409020805460018201546002830154600384015460049094015460ff9093169391929091906001600160a01b031685565b6004546001600160a01b031681565b610bef611b0e565b6000546001600160a01b03908116911614610c3f576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600a5460ff16610c8b576040805162461bcd60e51b815260206004820152601260248201527126b0b935b2ba1034b9903737ba1037b832b760711b604482015290519081900360640190fd5b610c9482611b6e565b610cd3576040805162461bcd60e51b815260206004820152601860248201526000805160206137cd833981519152604482015290519081900360640190fd5b610cde610af0611b8c565b15610d20576040805162461bcd60e51b815260206004820152600d60248201526c10985d18da0818d85b98db1959609a1b604482015290519081900360640190fd5b610d2b838383611eda565b610d77576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420436f6c6c61746572616c2056616c756560401b604482015290519081900360640190fd5b610b97838383612002565b600c546001600160a01b031681565b600a5460ff1681565b600d6020526000908152604090205481565b6005546001600160a01b031681565b610dc481611b6e565b610e12576040805162461bcd60e51b815260206004820152601a60248201527910dbdb1b185d195c985b08139bdd0815da1a5d195b1a5cdd195960321b604482015290519081900360640190fd5b610e1b82612226565b610e5c576040805162461bcd60e51b815260206004820152600d60248201526c2130ba31b41034b99037bb32b960991b604482015290519081900360640190fd5b610e668282611bb2565b15610eab576040805162461bcd60e51b815260206004820152601060248201526f10985d18da081a5cc818d85b98db195960821b604482015290519081900360640190fd5b610eb6828285612238565b610efa576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b97838383612273565b6000918252600f602090815260408084206001600160a01b03939093168452600592830190915290912080546001820154600283015460038401546004850154958501546006860154600787015460089097015460ff8088169a61010090980416989597949663ffffffff90941695949293919291565b610f84611b0e565b6000546001600160a01b03908116911614610fd4576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b610fdd826124de565b8015610fed5750610fed816124de565b611037576040805162461bcd60e51b8152602060048201526016602482015275496e76616c6964204665652050657263656e7461676560501b604482015290519081900360640190fd5b61104182826124eb565b5050565b61104d611b0e565b6000546001600160a01b0390811691161461109d576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116906000805160206137ad833981519152908390a3600080546001600160a01b0319169055565b6110dd611b0e565b6000546001600160a01b0390811691161461112d576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b038416179055611151826118d8565b600280546001600160a01b0319166001600160a01b038316179055611041612534565b61117d81611b6e565b6111cb576040805162461bcd60e51b815260206004820152601a60248201527910dbdb1b185d195c985b08139bdd0815da1a5d195b1a5cdd195960321b604482015290519081900360640190fd5b6111d482612226565b611215576040805162461bcd60e51b815260206004820152600d60248201526c2130ba31b41034b99037bb32b960991b604482015290519081900360640190fd5b61121f8282611bb2565b15611264576040805162461bcd60e51b815260206004820152601060248201526f10985d18da081a5cc818d85b98db195960821b604482015290519081900360640190fd5b61126f82828561258f565b6112b3576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b978383836125ca565b60095481565b60006112d184848461271d565b90505b9392505050565b600c546001600160a01b03163314611337576040805162461bcd60e51b815260206004820152601a60248201527944414f3a2063616c6c6572206973206e6f74207468652044414f60301b604482015290519081900360640190fd5b600a5460ff16611389576040805162461bcd60e51b815260206004820152601860248201527713585c9ad95d081a5cc8185b1c9958591e481c185d5cd95960421b604482015290519081900360640190fd5b600a5460ff166113a557600a805460ff191660011790556113b0565b600a805460ff191690555b6040517f5c975abbf8c4d6efa68fc896e233763eb503f2318260b7bf59b19412913788b290600090a1565b6113e3611b0e565b6000546001600160a01b03908116911614611433576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b61143c85611b6e565b61147b576040805162461bcd60e51b815260206004820152601860248201526000805160206137cd833981519152604482015290519081900360640190fd5b61148482612746565b6114cd576040805162461bcd60e51b8152602060048201526015602482015274496e76616c6964205265736572766520526174696f60581b604482015290519081900360640190fd5b6114da8585858585612758565b5050505050565b6000546001600160a01b031690565b6114fa8282611bb2565b611542576040805162461bcd60e51b815260206004820152601460248201527310985d18da081a5cc81b9bdd0818d85b98db195960621b604482015290519081900360640190fd5b61154d82828561258f565b611591576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b978383836127ee565b6115a4611b0e565b6000546001600160a01b039081169116146115f4576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b6115fd81611b6e565b61163c576040805162461bcd60e51b815260206004820152601860248201526000805160206137cd833981519152604482015290519081900360640190fd5b6109e481612940565b600b5481565b6002546001600160a01b031633146116a7576040805162461bcd60e51b815260206004820152601a60248201527905441503a2063616c6c6572206973206e6f7420746865205461760341b604482015290519081900360640190fd5b600480546040805163a9059cbb60e01b81526001600160a01b039283169381019390935260248301849052519084169163a9059cbb9160448083019260209291908290030181600087803b1580156116fe57600080fd5b505af1158015611712573d6000803e3d6000fd5b505050506040513d602081101561172857600080fd5b50505050565b60075481565b61173c611b0e565b6000546001600160a01b0390811691161461178c576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b6109e4816129ba565b61179f8282611bb2565b6117e4576040805162461bcd60e51b815260206004820152601160248201527010985d18da081b9bdd0818d85b98db1959607a1b604482015290519081900360640190fd5b6117ef828285612238565b611833576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b97838383612a04565b6006546001600160a01b031681565b6000611857611b8c565b905090565b600e602052600090815260409020805460018201546002830154600384015460049094015460ff909316939192909163ffffffff169085565b6001600160a01b03166000908152600e60205260409020805460018201546002830154600384015460049094015460ff909316949193909263ffffffff90911691565b6118e0611b0e565b6000546001600160a01b03908116911614611930576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b6001600160a01b0381166119755760405162461bcd60e51b81526004018080602001828103825260268152602001806137466026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216916000805160206137ad83398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b60085481565b6003546001600160a01b031681565b670de0b6b3a764000081565b6002546001600160a01b031681565b611a05611b0e565b6000546001600160a01b03908116911614611a55576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b611a5e85611b6e565b15611aaf576040805162461bcd60e51b815260206004820152601c60248201527b151bdad95b881a5cc8185b1c9958591e481dda1a5d195b1a5cdd195960221b604482015290519081900360640190fd5b611ab882612746565b611b01576040805162461bcd60e51b8152602060048201526015602482015274496e76616c6964205265736572766520526174696f60581b604482015290519081900360640190fd5b6114da8585858585612b1d565b3390565b6001600160a01b03811615155b919050565b600480546001600160a01b0319166001600160a01b0383169081179091556040517fe6131a64e93e9aa4ff38892c34d563c06dcc1e03b3d6897cc65f0903e2ad684890600090a250565b6001600160a01b03166000908152600e602052604090205460ff1690565b60075460009061185790611ba6438263ffffffff612bbe16565b9063ffffffff612bfd16565b6000828152600f602090815260408083206001600160a01b0385168452600501909152902054610100900460ff165b92915050565b600081158015906112d45750600354604080516370a0823160e01b81526001600160a01b0386811660048301529151859392909216916370a0823191602480820192602092909190829003018186803b158015611c4357600080fd5b505afa158015611c57573d6000803e3d6000fd5b505050506040513d6020811015611c6d57600080fd5b505110159392505050565b600080611c8484612c56565b60035460408051632770a7eb60e21b81526001600160a01b038a811660048301526024820189905291519496509294501691639dc29fac9160448082019260009290919082900301818387803b158015611cdd57600080fd5b505af1158015611cf1573d6000803e3d6000fd5b50505050600681015460088201546007830154611d0e9086612f82565b60078401556001600160a01b0387166000908152600a84016020526040902054611d3e908663ffffffff612f8216565b6001600160a01b0388166000908152600a85016020526040902055611d64838588612fda565b611d8d8360060154611d8184600b5461329e90919063ffffffff16565b9063ffffffff612f8216565b600b5560088301546001600160a01b0387166000908152600d6020526040902054611dc39190611d81908463ffffffff61329e16565b6001600160a01b0387166000908152600d6020526040902055611de5836132e0565b611e2f576040805162461bcd60e51b815260206004820152601660248201527514db1a5c1c1859d948195e18d959591cc81b1a5b5a5d60521b604482015290519081900360640190fd5b611e3886613340565b611e85576040805162461bcd60e51b8152602060048201526019602482015278496e73756666696369656e7420706f6f6c2062616c616e636560381b604482015290519081900360640190fd5b856001600160a01b031684886001600160a01b03167f8c103b7b044048ad0382ad31454a2ca34da952258d6526af3a57a9e799cbb7ec886040518082815260200191505060405180910390a450505050505050565b600081611ee9575060006112d4565b600083905082816001600160a01b03166370a08231876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f4557600080fd5b505afa158015611f59573d6000803e3d6000fd5b505050506040513d6020811015611f6f57600080fd5b505110801590611ff9575060408051636eb1769f60e11b81526001600160a01b0387811660048301523060248301529151859284169163dd62ed3e916044808301926020929190829003018186803b158015611fca57600080fd5b505afa158015611fde573d6000803e3d6000fd5b505050506040513d6020811015611ff457600080fd5b505110155b95945050505050565b60008061200e84612c56565b6000828152600f60205260408120600201549294509092509061205290670de0b6b3a76400009061204690879063ffffffff612bfd16565b9063ffffffff612bbe16565b90506000612066858363ffffffff61329e16565b90508115612087576004546120879088906001600160a01b03168885613399565b61209387308884613399565b6006830154600884015460058501546120b2908463ffffffff612f8216565b60058601556001600160a01b03891660009081526009860160205260409020546120e2908463ffffffff612f8216565b6001600160a01b038a16600090815260098701602052604090205561210885878a612fda565b6121258560060154611d8184600b5461329e90919063ffffffff16565b600b5560088501546001600160a01b0389166000908152600d602052604090205461215b9190611d81908463ffffffff61329e16565b6001600160a01b0389166000908152600d602052604090205561217d856132e0565b6121c7576040805162461bcd60e51b815260206004820152601660248201527514db1a5c1c1859d948195e18d959591cc81b1a5b5a5d60521b604482015290519081900360640190fd5b876001600160a01b0316868a6001600160a01b03167fecab89c21a18231f17bff6027decbe0682bc9916e969562a87781927b18b2e4d8787604051808381526020018281526020019250505060405180910390a4505050505050505050565b6000612230611b8c565b909110919050565b6000928352600f602090815260408085206001600160a01b0394851686526005018252808520929093168452600a9091019052902054151590565b6000828152600f602090815260408083206001600160a01b03808616855260059091018352818420600781015460088201549289168652600a8201909452918420549193926122ce929091612046919063ffffffff612bfd16565b6000858152600f60205260408120600301549192509061230390670de0b6b3a76400009061204690859063ffffffff612bfd16565b90506000612317838363ffffffff61329e16565b6001600160a01b0388166000908152600a8601602052604081205590508481156123f6576001600160a01b0386166000908152600d6020526040902054612364908563ffffffff61329e16565b6001600160a01b038088166000908152600d6020908152604080832094909455835163a9059cbb60e01b81528c841660048201526024810187905293519285169363a9059cbb9360448083019491928390030190829087803b1580156123c957600080fd5b505af11580156123dd573d6000803e3d6000fd5b505050506040513d60208110156123f357600080fd5b50505b821561248057600480546040805163a9059cbb60e01b81526001600160a01b039283169381019390935260248301869052519083169163a9059cbb9160448083019260209291908290030181600087803b15801561245357600080fd5b505af1158015612467573d6000803e3d6000fd5b505050506040513d602081101561247d57600080fd5b50505b856001600160a01b031687896001600160a01b03167f0eca047a22717e04fff16b883e2490c1490c953ec49bf7af9270fffddd8b53028686604051808381526020018281526020019250505060405180910390a45050505050505050565b670de0b6b3a76400001190565b60088290556009819055604080518381526020810183905281517f53482196ef67ac615caab1c3eca2c270acbfdcd75e57c5f24c1b98b10c8e6e04929181900390910190a15050565b600a5460ff1615612585576040805162461bcd60e51b815260206004820152601660248201527526b0b935b2ba1034b99030b63932b0b23c9037b832b760511b604482015290519081900360640190fd5b61258d613468565b565b6000928352600f602090815260408085206001600160a01b039485168652600501825280852092909316845260099091019052902054151590565b6000828152600f602090815260408083206001600160a01b03808616855260059182018452828520918201546006830154918916865260098301909452918420549093926126239290916120469163ffffffff612bfd16565b6001600160a01b0386166000908152600984016020526040812055905080156126ca57600b54612659908263ffffffff61329e16565b600b55600354604080516340c10f1960e01b81526001600160a01b03888116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b1580156126b157600080fd5b505af11580156126c5573d6000803e3d6000fd5b505050505b826001600160a01b031684866001600160a01b03167f1d3062ef0b6bc8ec6a09d7a72a4f2f8c332a0a1055605166c7ae24592c33a50b846040518082815260200191505060405180910390a45050505050565b60006112d16127358563ffffffff80861690612bfd16565b61204685611ba6620f424080612bfd565b620f424063ffffffff82161115919050565b6001600160a01b0385166000818152600e6020908152604091829020600181018890556002810187905560038101805463ffffffff881663ffffffff19909116811790915560049091018590558251888152918201879052818301526060810184905290517f1b8a18e7f392180ec571af2dd1c185cbc26951042ba1f62e87db979ee7643a2c9181900360800190a25050505050565b6000828152600f602090815260408083206001600160a01b03808616855260059091018352818420908716845260098101909252822080549290559080156128ed576001600160a01b0383166000908152600d6020526040902054612859908263ffffffff61329e16565b6001600160a01b038085166000818152600d6020908152604080832095909555845163a9059cbb60e01b8152938a1660048501526024840186905293518794929363a9059cbb936044808301949193928390030190829087803b1580156128bf57600080fd5b505af11580156128d3573d6000803e3d6000fd5b505050506040513d60208110156128e957600080fd5b5050505b826001600160a01b031684866001600160a01b03167feb3996b71a45309a78196a4ec37faf4860dccc26536b7f6232e078b47baf2cb8846040518082815260200191505060405180910390a45050505050565b612949816134a0565b6001600160a01b0381166000818152600e6020526040808220805460ff19168155600181018390556002810183905560038101805463ffffffff191690556004810183905590519092917fef578b3b1649eb50cb7766e79f596caa69b7de7e3fef0c0f4e678976a5d51e1591a25050565b600580546001600160a01b0319166001600160a01b0383169081179091556040517f050a79a49cc1dc3aeeccd8636685ad0469db41a9bd51254a34fc1cf616693d4190600090a250565b6000828152600f602090815260408083206001600160a01b038086168552600590910183528184209087168452600a810190925282208054929055908015612aca57600b54612a59908263ffffffff61329e16565b600b55600354604080516340c10f1960e01b81526001600160a01b03888116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015612ab157600080fd5b505af1158015612ac5573d6000803e3d6000fd5b505050505b826001600160a01b031684866001600160a01b03167f27335af9c3970a20380b78bda3af53f3ff8ad00e68ec511285c933afe4d42dd7846040518082815260200191505060405180910390a45050505050565b6001600160a01b0385166000818152600e6020908152604091829020805460ff19166001908117825581018890556002810187905560038101805463ffffffff881663ffffffff19909116811790915560049091018590558251888152918201879052818301526060810184905290517f769df79ace8fd94960b301fa390e66bcd330b25e4a6001f7107540a6d5e55eed9181900360800190a25050505050565b60006112d483836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b815250613575565b600082612c0c57506000611be1565b82820282848281612c1957fe5b04146112d45760405162461bcd60e51b815260040180806020018281038252602181526020018061376c6021913960400191505060405180910390fd5b6000806000612c63611b8c565b6000818152600f602090815260408083206001600160a01b0389168452600581019092529091208154929350909160ff16612db257600b54600354604080516318160ddd60e01b81529051612d1a93926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015612ce257600080fd5b505afa158015612cf6573d6000803e3d6000fd5b505050506040513d6020811015612d0c57600080fd5b50519063ffffffff612f8216565b600180840182905560085460028501819055600954600386018190556005546004870180546001600160a01b0319166001600160a01b039283161790819055875460ff19169094178755604080519586526020860193909352848301919091529190911660608301525184917f78ac2fc513d7c0ec8ae43a339f0da247ef78f9db22b6d6769163943f05c1a7fe919081900360800190a25b805460ff16612f76576001546040805163846a0a8960e01b81526001600160a01b03808a16600483015291518993929092169163846a0a899160248082019260009290919082900301818387803b158015612e0c57600080fd5b505af1158015612e20573d6000803e3d6000fd5b505050506001600160a01b0387166000908152600e6020526040902060019081015490840154612e4f91612f82565b60018301556001600160a01b038088166000908152600d6020908152604080832054600e8352928190206002015481516370a0823160e01b81523060048201529151612ecb95612ebf949293908816926370a0823192602480840193829003018186803b158015612ce257600080fd5b9063ffffffff61329e16565b600283018190556001600160a01b0388166000818152600e6020908152604091829020600380820154908801805463ffffffff191663ffffffff9283161790819055600492830154928901839055885460ff191660019081178a558901548551908152938401969096529490941681830152606081019390935251909186917f4bdd04ed9d5392ce48b8fc80abc6fdc0916ce12072be2d571c2d482416349a389181900360800190a3505b91935090915050915091565b6000828201838110156112d4576040805162461bcd60e51b815260206004820152601b60248201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604482015290519081900360640190fd5b600183015460028401546003850154600092612ffd92909163ffffffff1661271d565b90506000613025620f424063ffffffff16612046848860070154612bfd90919063ffffffff16565b9050846005015481111561314057600585015461304b90839061204690620f4240612bfd565b60068601819055600786015460009161306a919063ffffffff61329e16565b6000868152600f6020908152604080832060049081015460018c015460028d015460038e015485516349f9b0f760e01b815294850192909252602484015263ffffffff16604483015260648201869052915194955092936001600160a01b03909116926349f9b0f7926084808301939192829003018186803b1580156130ef57600080fd5b505afa158015613103573d6000803e3d6000fd5b505050506040513d602081101561311957600080fd5b50516005880154909150613133908263ffffffff612f8216565b6008880155506132309050565b60088501819055600585015460009061315f908363ffffffff61329e16565b6000868152600f6020908152604080832060049081015460018c015460028d015460038e01548551630a68039f60e21b815294850192909252602484015263ffffffff16604483015260648201869052915194955092936001600160a01b03909116926329a00e7c926084808301939192829003018186803b1580156131e457600080fd5b505afa1580156131f8573d6000803e3d6000fd5b505050506040513d602081101561320e57600080fd5b50516007880154909150613228908263ffffffff612f8216565b600688015550505b6005850154600686015460078701546008880154604080519485526020850193909352838301919091526060830152516001600160a01b0385169186917f365713522b06a53828592398186ff46abd75365ace3b70c1fad31872ae5da2229181900360800190a35050505050565b60006112d483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613617565b60018101546002820154600383015460009283926133039263ffffffff1661271d565b60048401549091508161331b57600192505050611b1f565b613326848383613671565b801561333857506133388483836136db565b949350505050565b6001600160a01b0381166000818152600d602090815260408083205481516370a0823160e01b8152306004820152915193948694919390926370a082319260248083019392829003018186803b158015611c4357600080fd5b604080516323b872dd60e01b81526001600160a01b0386811660048301528581166024830152604482018490529151918416916323b872dd916064808201926020929091908290030181600087803b1580156133f457600080fd5b505af1158015613408573d6000803e3d6000fd5b505050506040513d602081101561341e57600080fd5b5051611728576040805162461bcd60e51b8152602060048201526014602482015273151c985b9cd9995c88119c9bdb4811985a5b195960621b604482015290519081900360640190fd5b600a805460ff191660011790556040517f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a590600090a1565b6000806134ac83612c56565b80549193509150610100900460ff16610b9757805461ff00191661010017815560078101546006820154600b546134ee9291611d81919063ffffffff61329e16565b600b55600881015460058201546001600160a01b0385166000908152600d60205260409020546135299291612ebf919063ffffffff612f8216565b6001600160a01b0384166000818152600d6020526040808220939093559151909184917f75fe92dc34008d900951376546f4b5a99223fe53a5241a96516002ad912029e19190a3505050565b600081836136015760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156135c65781810151838201526020016135ae565b50505050905090810190601f1680156135f35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161360d57fe5b0495945050505050565b600081848411156136695760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156135c65781810151838201526020016135ae565b505050900390565b600583015460009061369490620f424090611ba690670de0b6b3a7640000612bfd565b6136c46136af670de0b6b3a76400008563ffffffff612f8216565b6006870154611ba6908763ffffffff612bfd16565b106136d1575060016112d4565b5060009392505050565b6000670de0b6b3a764000082106136f4575060016112d4565b600784015461372590611ba6613718670de0b6b3a76400008663ffffffff61329e16565b869063ffffffff612bfd16565b60088501546136c490620f424090611ba690670de0b6b3a7640000612bfd56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65728be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0546f6b656e206973206e6f742077686974656c69737465640000000000000000a2646970667358221220321d7a78b1ae86b81abb3669c2a3fc7977c5f98147a862cc9e38caed881f979464736f6c634300060200336261746368426c6f636b73206d7573742062652067726561746572207468616e207a65726f0000000000000000000000006b2d3b366c3417c46240ab62c2878ffda9861e7300000000000000000000000021bfbda47a0b4b5b1248c767ee49f7caa9b236970000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000e06748876bf92340d56c536388568cbcf679bc1100000000000000000000000077a9d21bef6a21a045503df0d8d58678392bafa5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106101c05760003560e01c80630aaffd2a146101c55780630d720bbc146101fa5780630f1ff5ea14610228578063177c14991461026b57806338af3eed146102cb5780633fae9bfb146102fc5780634162169f1461033257806347535d7b146103475780634afe6c47146103705780634b75f54f146103b55780635e6f6c77146103ca578063683dee471461040d5780636db794371461049d578063715018a6146104cd57806378aada53146104e257806378ea61031461051d5780637b9e86bf146105605780637cfab0cb146105755780638456cb59146105b15780638a9b1e2d146105c65780638da5cb5b146106175780639249be281461062c57806394f9059f1461066f5780639ba9dada146106a2578063a9059cbb146106b7578063c56f0f6c146106f0578063d5b49a7114610705578063dbbdf2fe14610738578063e0bab4c41461077b578063e720ac8e14610790578063eeb97d3b146107a5578063f190e4271461080b578063f2fde38b1461083e578063f77c479114610871578063f79c5c7c14610886578063f7c618c11461089b578063fc157cb4146108b0578063fd221031146108c5578063fd531e03146108da575b600080fd5b3480156101d157600080fd5b506101f8600480360360208110156101e857600080fd5b50356001600160a01b031661092b565b005b34801561020657600080fd5b5061020f6109e7565b6040805163ffffffff9092168252519081900360200190f35b34801561023457600080fd5b506101f86004803603606081101561024b57600080fd5b506001600160a01b038135811691602081013590911690604001356109ee565b34801561027757600080fd5b506102956004803603602081101561028e57600080fd5b5035610b9c565b60408051951515865260208601949094528484019290925260608401526001600160a01b03166080830152519081900360a00190f35b3480156102d757600080fd5b506102e0610bd8565b604080516001600160a01b039092168252519081900360200190f35b6101f86004803603606081101561031257600080fd5b506001600160a01b03813581169160208101359091169060400135610be7565b34801561033e57600080fd5b506102e0610d82565b34801561035357600080fd5b5061035c610d91565b604080519115158252519081900360200190f35b34801561037c57600080fd5b506103a36004803603602081101561039357600080fd5b50356001600160a01b0316610d9a565b60408051918252519081900360200190f35b3480156103c157600080fd5b506102e0610dac565b3480156103d657600080fd5b506101f8600480360360608110156103ed57600080fd5b506001600160a01b03813581169160208101359160409091013516610dbb565b34801561041957600080fd5b506104466004803603604081101561043057600080fd5b50803590602001356001600160a01b0316610f05565b604080519a15158b5298151560208b015289890197909752606089019590955263ffffffff909316608088015260a087019190915260c086015260e085015261010084015261012083015251908190036101400190f35b3480156104a957600080fd5b506101f8600480360360408110156104c057600080fd5b5080359060200135610f7c565b3480156104d957600080fd5b506101f8611045565b3480156104ee57600080fd5b506101f86004803603604081101561050557600080fd5b506001600160a01b03813581169160200135166110d5565b34801561052957600080fd5b506101f86004803603606081101561054057600080fd5b506001600160a01b03813581169160208101359160409091013516611174565b34801561056c57600080fd5b506103a36112be565b34801561058157600080fd5b506103a36004803603606081101561059857600080fd5b508035906020810135906040013563ffffffff166112c4565b3480156105bd57600080fd5b506101f86112db565b3480156105d257600080fd5b506101f8600480360360a08110156105e957600080fd5b506001600160a01b038135169060208101359060408101359063ffffffff60608201351690608001356113db565b34801561062357600080fd5b506102e06114e1565b34801561063857600080fd5b506101f86004803603606081101561064f57600080fd5b506001600160a01b038135811691602081013591604090910135166114f0565b34801561067b57600080fd5b506101f86004803603602081101561069257600080fd5b50356001600160a01b031661159c565b3480156106ae57600080fd5b506103a3611645565b3480156106c357600080fd5b506101f8600480360360408110156106da57600080fd5b506001600160a01b03813516906020013561164b565b3480156106fc57600080fd5b506103a361172e565b34801561071157600080fd5b506101f86004803603602081101561072857600080fd5b50356001600160a01b0316611734565b34801561074457600080fd5b506101f86004803603606081101561075b57600080fd5b506001600160a01b03813581169160208101359160409091013516611795565b34801561078757600080fd5b506102e061183e565b34801561079c57600080fd5b506103a361184d565b3480156107b157600080fd5b506107d8600480360360208110156107c857600080fd5b50356001600160a01b031661185c565b60408051951515865260208601949094528484019290925263ffffffff1660608401526080830152519081900360a00190f35b34801561081757600080fd5b506107d86004803603602081101561082e57600080fd5b50356001600160a01b0316611895565b34801561084a57600080fd5b506101f86004803603602081101561086157600080fd5b50356001600160a01b03166118d8565b34801561087d57600080fd5b506102e06119be565b34801561089257600080fd5b506103a36119cd565b3480156108a757600080fd5b506102e06119d3565b3480156108bc57600080fd5b506103a36119e2565b3480156108d157600080fd5b506102e06119ee565b3480156108e657600080fd5b506101f8600480360360a08110156108fd57600080fd5b506001600160a01b038135169060208101359060408101359063ffffffff60608201351690608001356119fd565b610933611b0e565b6000546001600160a01b03908116911614610983576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b61098c81611b12565b6109db576040805162461bcd60e51b815260206004820152601b60248201527a496e76616c69642042656e6566696369617279204164647265737360281b604482015290519081900360640190fd5b6109e481611b24565b50565b620f424081565b6109f6611b0e565b6000546001600160a01b03908116911614610a46576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600a5460ff16610a8b576040805162461bcd60e51b815260206004820152600b60248201526a24b9903737ba1037b832b760a91b604482015290519081900360640190fd5b610a9482611b6e565b610ae5576040805162461bcd60e51b815260206004820152601d60248201527f436f6c6c61746572616c206973206e6f742057686974656c6973746564000000604482015290519081900360640190fd5b610af6610af0611b8c565b83611bb2565b15610b3b576040805162461bcd60e51b815260206004820152601060248201526f10985d18da081a5cc818d85b98db195960821b604482015290519081900360640190fd5b610b458382611be7565b610b8c576040805162461bcd60e51b8152602060048201526013602482015272125b9d985b1a5908189bdb9908185b5bdd5b9d606a1b604482015290519081900360640190fd5b610b97838383611c78565b505050565b600f602052600090815260409020805460018201546002830154600384015460049094015460ff9093169391929091906001600160a01b031685565b6004546001600160a01b031681565b610bef611b0e565b6000546001600160a01b03908116911614610c3f576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600a5460ff16610c8b576040805162461bcd60e51b815260206004820152601260248201527126b0b935b2ba1034b9903737ba1037b832b760711b604482015290519081900360640190fd5b610c9482611b6e565b610cd3576040805162461bcd60e51b815260206004820152601860248201526000805160206137cd833981519152604482015290519081900360640190fd5b610cde610af0611b8c565b15610d20576040805162461bcd60e51b815260206004820152600d60248201526c10985d18da0818d85b98db1959609a1b604482015290519081900360640190fd5b610d2b838383611eda565b610d77576040805162461bcd60e51b8152602060048201526018602482015277496e76616c696420436f6c6c61746572616c2056616c756560401b604482015290519081900360640190fd5b610b97838383612002565b600c546001600160a01b031681565b600a5460ff1681565b600d6020526000908152604090205481565b6005546001600160a01b031681565b610dc481611b6e565b610e12576040805162461bcd60e51b815260206004820152601a60248201527910dbdb1b185d195c985b08139bdd0815da1a5d195b1a5cdd195960321b604482015290519081900360640190fd5b610e1b82612226565b610e5c576040805162461bcd60e51b815260206004820152600d60248201526c2130ba31b41034b99037bb32b960991b604482015290519081900360640190fd5b610e668282611bb2565b15610eab576040805162461bcd60e51b815260206004820152601060248201526f10985d18da081a5cc818d85b98db195960821b604482015290519081900360640190fd5b610eb6828285612238565b610efa576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b97838383612273565b6000918252600f602090815260408084206001600160a01b03939093168452600592830190915290912080546001820154600283015460038401546004850154958501546006860154600787015460089097015460ff8088169a61010090980416989597949663ffffffff90941695949293919291565b610f84611b0e565b6000546001600160a01b03908116911614610fd4576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b610fdd826124de565b8015610fed5750610fed816124de565b611037576040805162461bcd60e51b8152602060048201526016602482015275496e76616c6964204665652050657263656e7461676560501b604482015290519081900360640190fd5b61104182826124eb565b5050565b61104d611b0e565b6000546001600160a01b0390811691161461109d576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600080546040516001600160a01b03909116906000805160206137ad833981519152908390a3600080546001600160a01b0319169055565b6110dd611b0e565b6000546001600160a01b0390811691161461112d576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b038416179055611151826118d8565b600280546001600160a01b0319166001600160a01b038316179055611041612534565b61117d81611b6e565b6111cb576040805162461bcd60e51b815260206004820152601a60248201527910dbdb1b185d195c985b08139bdd0815da1a5d195b1a5cdd195960321b604482015290519081900360640190fd5b6111d482612226565b611215576040805162461bcd60e51b815260206004820152600d60248201526c2130ba31b41034b99037bb32b960991b604482015290519081900360640190fd5b61121f8282611bb2565b15611264576040805162461bcd60e51b815260206004820152601060248201526f10985d18da081a5cc818d85b98db195960821b604482015290519081900360640190fd5b61126f82828561258f565b6112b3576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b978383836125ca565b60095481565b60006112d184848461271d565b90505b9392505050565b600c546001600160a01b03163314611337576040805162461bcd60e51b815260206004820152601a60248201527944414f3a2063616c6c6572206973206e6f74207468652044414f60301b604482015290519081900360640190fd5b600a5460ff16611389576040805162461bcd60e51b815260206004820152601860248201527713585c9ad95d081a5cc8185b1c9958591e481c185d5cd95960421b604482015290519081900360640190fd5b600a5460ff166113a557600a805460ff191660011790556113b0565b600a805460ff191690555b6040517f5c975abbf8c4d6efa68fc896e233763eb503f2318260b7bf59b19412913788b290600090a1565b6113e3611b0e565b6000546001600160a01b03908116911614611433576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b61143c85611b6e565b61147b576040805162461bcd60e51b815260206004820152601860248201526000805160206137cd833981519152604482015290519081900360640190fd5b61148482612746565b6114cd576040805162461bcd60e51b8152602060048201526015602482015274496e76616c6964205265736572766520526174696f60581b604482015290519081900360640190fd5b6114da8585858585612758565b5050505050565b6000546001600160a01b031690565b6114fa8282611bb2565b611542576040805162461bcd60e51b815260206004820152601460248201527310985d18da081a5cc81b9bdd0818d85b98db195960621b604482015290519081900360640190fd5b61154d82828561258f565b611591576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b978383836127ee565b6115a4611b0e565b6000546001600160a01b039081169116146115f4576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b6115fd81611b6e565b61163c576040805162461bcd60e51b815260206004820152601860248201526000805160206137cd833981519152604482015290519081900360640190fd5b6109e481612940565b600b5481565b6002546001600160a01b031633146116a7576040805162461bcd60e51b815260206004820152601a60248201527905441503a2063616c6c6572206973206e6f7420746865205461760341b604482015290519081900360640190fd5b600480546040805163a9059cbb60e01b81526001600160a01b039283169381019390935260248301849052519084169163a9059cbb9160448083019260209291908290030181600087803b1580156116fe57600080fd5b505af1158015611712573d6000803e3d6000fd5b505050506040513d602081101561172857600080fd5b50505050565b60075481565b61173c611b0e565b6000546001600160a01b0390811691161461178c576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b6109e4816129ba565b61179f8282611bb2565b6117e4576040805162461bcd60e51b815260206004820152601160248201527010985d18da081b9bdd0818d85b98db1959607a1b604482015290519081900360640190fd5b6117ef828285612238565b611833576040805162461bcd60e51b815260206004820152601060248201526f4e6f7468696e6720746f20636c61696d60801b604482015290519081900360640190fd5b610b97838383612a04565b6006546001600160a01b031681565b6000611857611b8c565b905090565b600e602052600090815260409020805460018201546002830154600384015460049094015460ff909316939192909163ffffffff169085565b6001600160a01b03166000908152600e60205260409020805460018201546002830154600384015460049094015460ff909316949193909263ffffffff90911691565b6118e0611b0e565b6000546001600160a01b03908116911614611930576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b6001600160a01b0381166119755760405162461bcd60e51b81526004018080602001828103825260268152602001806137466026913960400191505060405180910390fd5b600080546040516001600160a01b03808516939216916000805160206137ad83398151915291a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b60085481565b6003546001600160a01b031681565b670de0b6b3a764000081565b6002546001600160a01b031681565b611a05611b0e565b6000546001600160a01b03908116911614611a55576040805162461bcd60e51b8152602060048201819052602482015260008051602061378d833981519152604482015290519081900360640190fd5b611a5e85611b6e565b15611aaf576040805162461bcd60e51b815260206004820152601c60248201527b151bdad95b881a5cc8185b1c9958591e481dda1a5d195b1a5cdd195960221b604482015290519081900360640190fd5b611ab882612746565b611b01576040805162461bcd60e51b8152602060048201526015602482015274496e76616c6964205265736572766520526174696f60581b604482015290519081900360640190fd5b6114da8585858585612b1d565b3390565b6001600160a01b03811615155b919050565b600480546001600160a01b0319166001600160a01b0383169081179091556040517fe6131a64e93e9aa4ff38892c34d563c06dcc1e03b3d6897cc65f0903e2ad684890600090a250565b6001600160a01b03166000908152600e602052604090205460ff1690565b60075460009061185790611ba6438263ffffffff612bbe16565b9063ffffffff612bfd16565b6000828152600f602090815260408083206001600160a01b0385168452600501909152902054610100900460ff165b92915050565b600081158015906112d45750600354604080516370a0823160e01b81526001600160a01b0386811660048301529151859392909216916370a0823191602480820192602092909190829003018186803b158015611c4357600080fd5b505afa158015611c57573d6000803e3d6000fd5b505050506040513d6020811015611c6d57600080fd5b505110159392505050565b600080611c8484612c56565b60035460408051632770a7eb60e21b81526001600160a01b038a811660048301526024820189905291519496509294501691639dc29fac9160448082019260009290919082900301818387803b158015611cdd57600080fd5b505af1158015611cf1573d6000803e3d6000fd5b50505050600681015460088201546007830154611d0e9086612f82565b60078401556001600160a01b0387166000908152600a84016020526040902054611d3e908663ffffffff612f8216565b6001600160a01b0388166000908152600a85016020526040902055611d64838588612fda565b611d8d8360060154611d8184600b5461329e90919063ffffffff16565b9063ffffffff612f8216565b600b5560088301546001600160a01b0387166000908152600d6020526040902054611dc39190611d81908463ffffffff61329e16565b6001600160a01b0387166000908152600d6020526040902055611de5836132e0565b611e2f576040805162461bcd60e51b815260206004820152601660248201527514db1a5c1c1859d948195e18d959591cc81b1a5b5a5d60521b604482015290519081900360640190fd5b611e3886613340565b611e85576040805162461bcd60e51b8152602060048201526019602482015278496e73756666696369656e7420706f6f6c2062616c616e636560381b604482015290519081900360640190fd5b856001600160a01b031684886001600160a01b03167f8c103b7b044048ad0382ad31454a2ca34da952258d6526af3a57a9e799cbb7ec886040518082815260200191505060405180910390a450505050505050565b600081611ee9575060006112d4565b600083905082816001600160a01b03166370a08231876040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f4557600080fd5b505afa158015611f59573d6000803e3d6000fd5b505050506040513d6020811015611f6f57600080fd5b505110801590611ff9575060408051636eb1769f60e11b81526001600160a01b0387811660048301523060248301529151859284169163dd62ed3e916044808301926020929190829003018186803b158015611fca57600080fd5b505afa158015611fde573d6000803e3d6000fd5b505050506040513d6020811015611ff457600080fd5b505110155b95945050505050565b60008061200e84612c56565b6000828152600f60205260408120600201549294509092509061205290670de0b6b3a76400009061204690879063ffffffff612bfd16565b9063ffffffff612bbe16565b90506000612066858363ffffffff61329e16565b90508115612087576004546120879088906001600160a01b03168885613399565b61209387308884613399565b6006830154600884015460058501546120b2908463ffffffff612f8216565b60058601556001600160a01b03891660009081526009860160205260409020546120e2908463ffffffff612f8216565b6001600160a01b038a16600090815260098701602052604090205561210885878a612fda565b6121258560060154611d8184600b5461329e90919063ffffffff16565b600b5560088501546001600160a01b0389166000908152600d602052604090205461215b9190611d81908463ffffffff61329e16565b6001600160a01b0389166000908152600d602052604090205561217d856132e0565b6121c7576040805162461bcd60e51b815260206004820152601660248201527514db1a5c1c1859d948195e18d959591cc81b1a5b5a5d60521b604482015290519081900360640190fd5b876001600160a01b0316868a6001600160a01b03167fecab89c21a18231f17bff6027decbe0682bc9916e969562a87781927b18b2e4d8787604051808381526020018281526020019250505060405180910390a4505050505050505050565b6000612230611b8c565b909110919050565b6000928352600f602090815260408085206001600160a01b0394851686526005018252808520929093168452600a9091019052902054151590565b6000828152600f602090815260408083206001600160a01b03808616855260059091018352818420600781015460088201549289168652600a8201909452918420549193926122ce929091612046919063ffffffff612bfd16565b6000858152600f60205260408120600301549192509061230390670de0b6b3a76400009061204690859063ffffffff612bfd16565b90506000612317838363ffffffff61329e16565b6001600160a01b0388166000908152600a8601602052604081205590508481156123f6576001600160a01b0386166000908152600d6020526040902054612364908563ffffffff61329e16565b6001600160a01b038088166000908152600d6020908152604080832094909455835163a9059cbb60e01b81528c841660048201526024810187905293519285169363a9059cbb9360448083019491928390030190829087803b1580156123c957600080fd5b505af11580156123dd573d6000803e3d6000fd5b505050506040513d60208110156123f357600080fd5b50505b821561248057600480546040805163a9059cbb60e01b81526001600160a01b039283169381019390935260248301869052519083169163a9059cbb9160448083019260209291908290030181600087803b15801561245357600080fd5b505af1158015612467573d6000803e3d6000fd5b505050506040513d602081101561247d57600080fd5b50505b856001600160a01b031687896001600160a01b03167f0eca047a22717e04fff16b883e2490c1490c953ec49bf7af9270fffddd8b53028686604051808381526020018281526020019250505060405180910390a45050505050505050565b670de0b6b3a76400001190565b60088290556009819055604080518381526020810183905281517f53482196ef67ac615caab1c3eca2c270acbfdcd75e57c5f24c1b98b10c8e6e04929181900390910190a15050565b600a5460ff1615612585576040805162461bcd60e51b815260206004820152601660248201527526b0b935b2ba1034b99030b63932b0b23c9037b832b760511b604482015290519081900360640190fd5b61258d613468565b565b6000928352600f602090815260408085206001600160a01b039485168652600501825280852092909316845260099091019052902054151590565b6000828152600f602090815260408083206001600160a01b03808616855260059182018452828520918201546006830154918916865260098301909452918420549093926126239290916120469163ffffffff612bfd16565b6001600160a01b0386166000908152600984016020526040812055905080156126ca57600b54612659908263ffffffff61329e16565b600b55600354604080516340c10f1960e01b81526001600160a01b03888116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b1580156126b157600080fd5b505af11580156126c5573d6000803e3d6000fd5b505050505b826001600160a01b031684866001600160a01b03167f1d3062ef0b6bc8ec6a09d7a72a4f2f8c332a0a1055605166c7ae24592c33a50b846040518082815260200191505060405180910390a45050505050565b60006112d16127358563ffffffff80861690612bfd16565b61204685611ba6620f424080612bfd565b620f424063ffffffff82161115919050565b6001600160a01b0385166000818152600e6020908152604091829020600181018890556002810187905560038101805463ffffffff881663ffffffff19909116811790915560049091018590558251888152918201879052818301526060810184905290517f1b8a18e7f392180ec571af2dd1c185cbc26951042ba1f62e87db979ee7643a2c9181900360800190a25050505050565b6000828152600f602090815260408083206001600160a01b03808616855260059091018352818420908716845260098101909252822080549290559080156128ed576001600160a01b0383166000908152600d6020526040902054612859908263ffffffff61329e16565b6001600160a01b038085166000818152600d6020908152604080832095909555845163a9059cbb60e01b8152938a1660048501526024840186905293518794929363a9059cbb936044808301949193928390030190829087803b1580156128bf57600080fd5b505af11580156128d3573d6000803e3d6000fd5b505050506040513d60208110156128e957600080fd5b5050505b826001600160a01b031684866001600160a01b03167feb3996b71a45309a78196a4ec37faf4860dccc26536b7f6232e078b47baf2cb8846040518082815260200191505060405180910390a45050505050565b612949816134a0565b6001600160a01b0381166000818152600e6020526040808220805460ff19168155600181018390556002810183905560038101805463ffffffff191690556004810183905590519092917fef578b3b1649eb50cb7766e79f596caa69b7de7e3fef0c0f4e678976a5d51e1591a25050565b600580546001600160a01b0319166001600160a01b0383169081179091556040517f050a79a49cc1dc3aeeccd8636685ad0469db41a9bd51254a34fc1cf616693d4190600090a250565b6000828152600f602090815260408083206001600160a01b038086168552600590910183528184209087168452600a810190925282208054929055908015612aca57600b54612a59908263ffffffff61329e16565b600b55600354604080516340c10f1960e01b81526001600160a01b03888116600483015260248201859052915191909216916340c10f1991604480830192600092919082900301818387803b158015612ab157600080fd5b505af1158015612ac5573d6000803e3d6000fd5b505050505b826001600160a01b031684866001600160a01b03167f27335af9c3970a20380b78bda3af53f3ff8ad00e68ec511285c933afe4d42dd7846040518082815260200191505060405180910390a45050505050565b6001600160a01b0385166000818152600e6020908152604091829020805460ff19166001908117825581018890556002810187905560038101805463ffffffff881663ffffffff19909116811790915560049091018590558251888152918201879052818301526060810184905290517f769df79ace8fd94960b301fa390e66bcd330b25e4a6001f7107540a6d5e55eed9181900360800190a25050505050565b60006112d483836040518060400160405280601a815260200179536166654d6174683a206469766973696f6e206279207a65726f60301b815250613575565b600082612c0c57506000611be1565b82820282848281612c1957fe5b04146112d45760405162461bcd60e51b815260040180806020018281038252602181526020018061376c6021913960400191505060405180910390fd5b6000806000612c63611b8c565b6000818152600f602090815260408083206001600160a01b0389168452600581019092529091208154929350909160ff16612db257600b54600354604080516318160ddd60e01b81529051612d1a93926001600160a01b0316916318160ddd916004808301926020929190829003018186803b158015612ce257600080fd5b505afa158015612cf6573d6000803e3d6000fd5b505050506040513d6020811015612d0c57600080fd5b50519063ffffffff612f8216565b600180840182905560085460028501819055600954600386018190556005546004870180546001600160a01b0319166001600160a01b039283161790819055875460ff19169094178755604080519586526020860193909352848301919091529190911660608301525184917f78ac2fc513d7c0ec8ae43a339f0da247ef78f9db22b6d6769163943f05c1a7fe919081900360800190a25b805460ff16612f76576001546040805163846a0a8960e01b81526001600160a01b03808a16600483015291518993929092169163846a0a899160248082019260009290919082900301818387803b158015612e0c57600080fd5b505af1158015612e20573d6000803e3d6000fd5b505050506001600160a01b0387166000908152600e6020526040902060019081015490840154612e4f91612f82565b60018301556001600160a01b038088166000908152600d6020908152604080832054600e8352928190206002015481516370a0823160e01b81523060048201529151612ecb95612ebf949293908816926370a0823192602480840193829003018186803b158015612ce257600080fd5b9063ffffffff61329e16565b600283018190556001600160a01b0388166000818152600e6020908152604091829020600380820154908801805463ffffffff191663ffffffff9283161790819055600492830154928901839055885460ff191660019081178a558901548551908152938401969096529490941681830152606081019390935251909186917f4bdd04ed9d5392ce48b8fc80abc6fdc0916ce12072be2d571c2d482416349a389181900360800190a3505b91935090915050915091565b6000828201838110156112d4576040805162461bcd60e51b815260206004820152601b60248201527a536166654d6174683a206164646974696f6e206f766572666c6f7760281b604482015290519081900360640190fd5b600183015460028401546003850154600092612ffd92909163ffffffff1661271d565b90506000613025620f424063ffffffff16612046848860070154612bfd90919063ffffffff16565b9050846005015481111561314057600585015461304b90839061204690620f4240612bfd565b60068601819055600786015460009161306a919063ffffffff61329e16565b6000868152600f6020908152604080832060049081015460018c015460028d015460038e015485516349f9b0f760e01b815294850192909252602484015263ffffffff16604483015260648201869052915194955092936001600160a01b03909116926349f9b0f7926084808301939192829003018186803b1580156130ef57600080fd5b505afa158015613103573d6000803e3d6000fd5b505050506040513d602081101561311957600080fd5b50516005880154909150613133908263ffffffff612f8216565b6008880155506132309050565b60088501819055600585015460009061315f908363ffffffff61329e16565b6000868152600f6020908152604080832060049081015460018c015460028d015460038e01548551630a68039f60e21b815294850192909252602484015263ffffffff16604483015260648201869052915194955092936001600160a01b03909116926329a00e7c926084808301939192829003018186803b1580156131e457600080fd5b505afa1580156131f8573d6000803e3d6000fd5b505050506040513d602081101561320e57600080fd5b50516007880154909150613228908263ffffffff612f8216565b600688015550505b6005850154600686015460078701546008880154604080519485526020850193909352838301919091526060830152516001600160a01b0385169186917f365713522b06a53828592398186ff46abd75365ace3b70c1fad31872ae5da2229181900360800190a35050505050565b60006112d483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250613617565b60018101546002820154600383015460009283926133039263ffffffff1661271d565b60048401549091508161331b57600192505050611b1f565b613326848383613671565b801561333857506133388483836136db565b949350505050565b6001600160a01b0381166000818152600d602090815260408083205481516370a0823160e01b8152306004820152915193948694919390926370a082319260248083019392829003018186803b158015611c4357600080fd5b604080516323b872dd60e01b81526001600160a01b0386811660048301528581166024830152604482018490529151918416916323b872dd916064808201926020929091908290030181600087803b1580156133f457600080fd5b505af1158015613408573d6000803e3d6000fd5b505050506040513d602081101561341e57600080fd5b5051611728576040805162461bcd60e51b8152602060048201526014602482015273151c985b9cd9995c88119c9bdb4811985a5b195960621b604482015290519081900360640190fd5b600a805460ff191660011790556040517f59ebeb90bc63057b6515673c3ecf9438e5058bca0f92585014eced636878c9a590600090a1565b6000806134ac83612c56565b80549193509150610100900460ff16610b9757805461ff00191661010017815560078101546006820154600b546134ee9291611d81919063ffffffff61329e16565b600b55600881015460058201546001600160a01b0385166000908152600d60205260409020546135299291612ebf919063ffffffff612f8216565b6001600160a01b0384166000818152600d6020526040808220939093559151909184917f75fe92dc34008d900951376546f4b5a99223fe53a5241a96516002ad912029e19190a3505050565b600081836136015760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156135c65781810151838201526020016135ae565b50505050905090810190601f1680156135f35780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b50600083858161360d57fe5b0495945050505050565b600081848411156136695760405162461bcd60e51b81526020600482018181528351602484015283519092839260449091019190850190808383600083156135c65781810151838201526020016135ae565b505050900390565b600583015460009061369490620f424090611ba690670de0b6b3a7640000612bfd565b6136c46136af670de0b6b3a76400008563ffffffff612f8216565b6006870154611ba6908763ffffffff612bfd16565b106136d1575060016112d4565b5060009392505050565b6000670de0b6b3a764000082106136f4575060016112d4565b600784015461372590611ba6613718670de0b6b3a76400008663ffffffff61329e16565b869063ffffffff612bfd16565b60088501546136c490620f424090611ba690670de0b6b3a7640000612bfd56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65728be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0546f6b656e206973206e6f742077686974656c69737465640000000000000000a2646970667358221220321d7a78b1ae86b81abb3669c2a3fc7977c5f98147a862cc9e38caed881f979464736f6c63430006020033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000006b2d3b366c3417c46240ab62c2878ffda9861e7300000000000000000000000021bfbda47a0b4b5b1248c767ee49f7caa9b236970000000000000000000000006b175474e89094c44da98b954eedeac495271d0f000000000000000000000000e06748876bf92340d56c536388568cbcf679bc1100000000000000000000000077a9d21bef6a21a045503df0d8d58678392bafa5000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _formula (address): 0x6b2D3B366C3417C46240ab62c2878FfdA9861E73
Arg [1] : _rewardToken (address): 0x21BfBDa47A0B4B5b1248c767Ee49F7caA9B23697
Arg [2] : _dai (address): 0x6B175474E89094C44Da98b954EedeAC495271d0F
Arg [3] : _dao (address): 0xe06748876bf92340D56C536388568cbcf679bc11
Arg [4] : _beneficiary (address): 0x77A9d21bEf6a21a045503df0d8D58678392BAFa5
Arg [5] : _batchBlocks (uint256): 1
Arg [6] : _buyFeePct (uint256): 0
Arg [7] : _sellFeePct (uint256): 0
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000006b2d3b366c3417c46240ab62c2878ffda9861e73
Arg [1] : 00000000000000000000000021bfbda47a0b4b5b1248c767ee49f7caa9b23697
Arg [2] : 0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f
Arg [3] : 000000000000000000000000e06748876bf92340d56c536388568cbcf679bc11
Arg [4] : 00000000000000000000000077a9d21bef6a21a045503df0d8d58678392bafa5
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
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.