Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
12341542 | 1283 days ago | 0.7351695 ETH | ||||
12341542 | 1283 days ago | 0.7351695 ETH | ||||
12336461 | 1284 days ago | 0.103983 ETH | ||||
12336461 | 1284 days ago | 0.103983 ETH | ||||
12329310 | 1285 days ago | 0.879925 ETH | ||||
12329310 | 1285 days ago | 0.879925 ETH | ||||
12329307 | 1285 days ago | 15.956143 ETH | ||||
12329307 | 1285 days ago | 15.956143 ETH | ||||
12319164 | 1287 days ago | 0.229878 ETH | ||||
12319164 | 1287 days ago | 0.229878 ETH | ||||
12311730 | 1288 days ago | 0.11016 ETH | ||||
12311730 | 1288 days ago | 0.11016 ETH | ||||
12311723 | 1288 days ago | 2.203092 ETH | ||||
12311723 | 1288 days ago | 2.203092 ETH | ||||
12311721 | 1288 days ago | 0.137781 ETH | ||||
12311721 | 1288 days ago | 0.137781 ETH | ||||
12306451 | 1289 days ago | 0.1533 ETH | ||||
12306451 | 1289 days ago | 0.1533 ETH | ||||
12306447 | 1289 days ago | 3.06621 ETH | ||||
12306447 | 1289 days ago | 3.06621 ETH | ||||
12304505 | 1289 days ago | 0.1829 ETH | ||||
12304505 | 1289 days ago | 0.1829 ETH | ||||
12293399 | 1291 days ago | 0.409833 ETH | ||||
12293399 | 1291 days ago | 0.409833 ETH | ||||
12293266 | 1291 days ago | 0.769311 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
UniswapDappV2
Compiler Version
v0.5.12+commit.7709ece9
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-07-01 */ // File: contracts/lib/math/SafeMath.sol pragma solidity 0.5.12; /** * @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) { require(b <= a, "SafeMath: subtraction overflow"); 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-solidity/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) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); 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) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } } // File: contracts/lib/utils/ReentrancyGuard.sol pragma solidity ^0.5.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier * available, which can be aplied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. */ contract ReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; constructor () internal { // The counter starts at one to prevent changing it from zero to a non-zero // value, which is a more expensive operation. _guardCounter = 1; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call"); } } // File: contracts/extensions/BrokerExtension.sol pragma solidity 0.5.12; interface Broker { function owner() external returns (address); function isAdmin(address _user) external returns(bool); function markNonce(uint256 _nonce) external; } contract BrokerExtension is ReentrancyGuard { Broker public broker; modifier onlyAdmin() { require(broker.isAdmin(msg.sender), "Invalid msg.sender"); _; } modifier onlyOwner() { require(broker.owner() == msg.sender, "Invalid msg.sender"); _; } function initializeBroker(address _brokerAddress) external { require(_brokerAddress != address(0), "Invalid _brokerAddress"); require(address(broker) == address(0), "Broker already set"); broker = Broker(_brokerAddress); } } // File: contracts/Utils.sol pragma solidity 0.5.12; interface ERC20 { function balanceOf(address account) external view returns (uint256); } interface MarketDapp { // Returns the address to approve tokens for function tokenReceiver(address[] calldata assetIds, uint256[] calldata dataValues, address[] calldata addresses) external view returns(address); function trade(address[] calldata assetIds, uint256[] calldata dataValues, address[] calldata addresses, address payable recipient) external payable; } /// @title Util functions for the BrokerV2 contract for Switcheo Exchange /// @author Switcheo Network /// @notice Functions were moved from the BrokerV2 contract into this contract /// so that the BrokerV2 contract would not exceed the maximum contract size of /// 24 KB. library Utils { using SafeMath for uint256; // The constants for EIP-712 are precompiled to reduce contract size, // the original values are left here for reference and verification. // // bytes32 public constant EIP712_DOMAIN_TYPEHASH = keccak256(abi.encodePacked( // "EIP712Domain(", // "string name,", // "string version,", // "uint256 chainId,", // "address verifyingContract,", // "bytes32 salt", // ")" // )); // bytes32 public constant EIP712_DOMAIN_TYPEHASH = 0xd87cd6ef79d4e2b95e15ce8abf732db51ec771f1ca2edccf22a46c729ac56472; // // bytes32 public constant CONTRACT_NAME = keccak256("Switcheo Exchange"); // bytes32 public constant CONTRACT_VERSION = keccak256("2"); // uint256 public constant CHAIN_ID = 3; // TODO: Update this before deploying // address public constant VERIFYING_CONTRACT = address(1); // TODO: Update this before deploying // bytes32 public constant SALT = keccak256("switcheo-eth-salt"); // bytes32 public constant DOMAIN_SEPARATOR = keccak256(abi.encode( // EIP712_DOMAIN_TYPEHASH, // CONTRACT_NAME, // CONTRACT_VERSION, // CHAIN_ID, // VERIFYING_CONTRACT, // SALT // )); bytes32 public constant DOMAIN_SEPARATOR = 0x14f697e312cdba1c10a1eb5c87d96fa22b63aef9dc39592568387471319ea630; // bytes32 public constant OFFER_TYPEHASH = keccak256(abi.encodePacked( // "Offer(", // "address maker,", // "address offerAssetId,", // "uint256 offerAmount,", // "address wantAssetId,", // "uint256 wantAmount,", // "address feeAssetId,", // "uint256 feeAmount,", // "uint256 nonce", // ")" // )); bytes32 public constant OFFER_TYPEHASH = 0xf845c83a8f7964bc8dd1a092d28b83573b35be97630a5b8a3b8ae2ae79cd9260; // bytes32 public constant CANCEL_TYPEHASH = keccak256(abi.encodePacked( // "Cancel(", // "bytes32 offerHash,", // "address feeAssetId,", // "uint256 feeAmount,", // ")" // )); bytes32 public constant CANCEL_TYPEHASH = 0x46f6d088b1f0ff5a05c3f232c4567f2df96958e05457e6c0e1221dcee7d69c18; // bytes32 public constant FILL_TYPEHASH = keccak256(abi.encodePacked( // "Fill(", // "address filler,", // "address offerAssetId,", // "uint256 offerAmount,", // "address wantAssetId,", // "uint256 wantAmount,", // "address feeAssetId,", // "uint256 feeAmount,", // "uint256 nonce", // ")" // )); bytes32 public constant FILL_TYPEHASH = 0x5f59dbc3412a4575afed909d028055a91a4250ce92235f6790c155a4b2669e99; // The Ether token address is set as the constant 0x00 for backwards // compatibility address private constant ETHER_ADDR = address(0); uint256 private constant mask8 = ~(~uint256(0) << 8); uint256 private constant mask16 = ~(~uint256(0) << 16); uint256 private constant mask24 = ~(~uint256(0) << 24); uint256 private constant mask32 = ~(~uint256(0) << 32); uint256 private constant mask40 = ~(~uint256(0) << 40); uint256 private constant mask48 = ~(~uint256(0) << 48); uint256 private constant mask56 = ~(~uint256(0) << 56); uint256 private constant mask120 = ~(~uint256(0) << 120); uint256 private constant mask128 = ~(~uint256(0) << 128); uint256 private constant mask136 = ~(~uint256(0) << 136); uint256 private constant mask144 = ~(~uint256(0) << 144); event Trade( address maker, address taker, address makerGiveAsset, uint256 makerGiveAmount, address fillerGiveAsset, uint256 fillerGiveAmount ); /// @dev Calculates the balance increments for a set of trades /// @param _values The _values param from the trade method /// @param _incrementsLength Should match the value of _addresses.length / 2 /// from the trade method /// @return An array of increments function calculateTradeIncrements( uint256[] memory _values, uint256 _incrementsLength ) public pure returns (uint256[] memory) { uint256[] memory increments = new uint256[](_incrementsLength); _creditFillBalances(increments, _values); _creditMakerBalances(increments, _values); _creditMakerFeeBalances(increments, _values); return increments; } /// @dev Calculates the balance decrements for a set of trades /// @param _values The _values param from the trade method /// @param _decrementsLength Should match the value of _addresses.length / 2 /// from the trade method /// @return An array of decrements function calculateTradeDecrements( uint256[] memory _values, uint256 _decrementsLength ) public pure returns (uint256[] memory) { uint256[] memory decrements = new uint256[](_decrementsLength); _deductFillBalances(decrements, _values); _deductMakerBalances(decrements, _values); return decrements; } /// @dev Calculates the balance increments for a set of network trades /// @param _values The _values param from the networkTrade method /// @param _incrementsLength Should match the value of _addresses.length / 2 /// from the networkTrade method /// @return An array of increments function calculateNetworkTradeIncrements( uint256[] memory _values, uint256 _incrementsLength ) public pure returns (uint256[] memory) { uint256[] memory increments = new uint256[](_incrementsLength); _creditMakerBalances(increments, _values); _creditMakerFeeBalances(increments, _values); return increments; } /// @dev Calculates the balance decrements for a set of network trades /// @param _values The _values param from the trade method /// @param _decrementsLength Should match the value of _addresses.length / 2 /// from the networkTrade method /// @return An array of decrements function calculateNetworkTradeDecrements( uint256[] memory _values, uint256 _decrementsLength ) public pure returns (uint256[] memory) { uint256[] memory decrements = new uint256[](_decrementsLength); _deductMakerBalances(decrements, _values); return decrements; } /// @dev Validates `BrokerV2.trade` parameters to ensure trade fairness, /// see `BrokerV2.trade` for param details. /// @param _values Values from `trade` /// @param _hashes Hashes from `trade` /// @param _addresses Addresses from `trade` function validateTrades( uint256[] memory _values, bytes32[] memory _hashes, address[] memory _addresses, address _operator ) public returns (bytes32[] memory) { _validateTradeInputLengths(_values, _hashes); _validateUniqueOffers(_values); _validateMatches(_values, _addresses); _validateFillAmounts(_values); _validateTradeData(_values, _addresses, _operator); // validate signatures of all offers _validateTradeSignatures( _values, _hashes, _addresses, OFFER_TYPEHASH, 0, _values[0] & mask8 // numOffers ); // validate signatures of all fills _validateTradeSignatures( _values, _hashes, _addresses, FILL_TYPEHASH, _values[0] & mask8, // numOffers (_values[0] & mask8) + ((_values[0] & mask16) >> 8) // numOffers + numFills ); _emitTradeEvents(_values, _addresses, new address[](0), false); return _hashes; } /// @dev Validates `BrokerV2.networkTrade` parameters to ensure trade fairness, /// see `BrokerV2.networkTrade` for param details. /// @param _values Values from `networkTrade` /// @param _hashes Hashes from `networkTrade` /// @param _addresses Addresses from `networkTrade` /// @param _operator Address of the `BrokerV2.operator` function validateNetworkTrades( uint256[] memory _values, bytes32[] memory _hashes, address[] memory _addresses, address _operator ) public pure returns (bytes32[] memory) { _validateNetworkTradeInputLengths(_values, _hashes); _validateUniqueOffers(_values); _validateNetworkMatches(_values, _addresses, _operator); _validateTradeData(_values, _addresses, _operator); // validate signatures of all offers _validateTradeSignatures( _values, _hashes, _addresses, OFFER_TYPEHASH, 0, _values[0] & mask8 // numOffers ); return _hashes; } /// @dev Executes trades against external markets, /// see `BrokerV2.networkTrade` for param details. /// @param _values Values from `networkTrade` /// @param _addresses Addresses from `networkTrade` /// @param _marketDapps See `BrokerV2.marketDapps` function performNetworkTrades( uint256[] memory _values, address[] memory _addresses, address[] memory _marketDapps ) public returns (uint256[] memory) { uint256[] memory increments = new uint256[](_addresses.length / 2); // i = 1 + numOffers * 2 uint256 i = 1 + (_values[0] & mask8) * 2; uint256 end = _values.length; // loop matches for(i; i < end; i++) { uint256[] memory data = new uint256[](9); data[0] = _values[i]; // match data data[1] = data[0] & mask8; // offerIndex data[2] = (data[0] & mask24) >> 16; // operator.surplusAssetIndex data[3] = _values[data[1] * 2 + 1]; // offer.dataA data[4] = _values[data[1] * 2 + 2]; // offer.dataB data[5] = ((data[3] & mask16) >> 8); // maker.offerAssetIndex data[6] = ((data[3] & mask24) >> 16); // maker.wantAssetIndex // amount of offerAssetId to take from the offer is equal to the match.takeAmount data[7] = data[0] >> 128; // expected amount to receive is: matchData.takeAmount * offer.wantAmount / offer.offerAmount data[8] = data[7].mul(data[4] >> 128).div(data[4] & mask128); address[] memory assetIds = new address[](3); assetIds[0] = _addresses[data[5] * 2 + 1]; // offer.offerAssetId assetIds[1] = _addresses[data[6] * 2 + 1]; // offer.wantAssetId assetIds[2] = _addresses[data[2] * 2 + 1]; // surplusAssetId uint256[] memory dataValues = new uint256[](3); dataValues[0] = data[7]; // the proportion of offerAmount to offer dataValues[1] = data[8]; // the proportion of wantAmount to receive for the offer dataValues[2] = data[0]; // match data increments[data[2]] = _performNetworkTrade( assetIds, dataValues, _marketDapps, _addresses ); } _emitTradeEvents(_values, _addresses, _marketDapps, true); return increments; } /// @dev Validates the signature of a cancel invocation /// @param _values The _values param from the cancel method /// @param _hashes The _hashes param from the cancel method /// @param _addresses The _addresses param from the cancel method function validateCancel( uint256[] memory _values, bytes32[] memory _hashes, address[] memory _addresses ) public pure { bytes32 offerHash = hashOffer(_values, _addresses); bytes32 cancelHash = keccak256(abi.encode( CANCEL_TYPEHASH, offerHash, _addresses[4], _values[1] >> 128 )); validateSignature( cancelHash, _addresses[0], // maker uint8((_values[2] & mask144) >> 136), // v _hashes[0], // r _hashes[1], // s ((_values[2] & mask136) >> 128) != 0 // prefixedSignature ); } /// @dev Hashes an offer for the cancel method /// @param _values The _values param from the cancel method /// @param _addresses THe _addresses param from the cancel method /// @return The hash of the offer function hashOffer( uint256[] memory _values, address[] memory _addresses ) public pure returns (bytes32) { return keccak256(abi.encode( OFFER_TYPEHASH, _addresses[0], // maker _addresses[1], // offerAssetId _values[0] & mask128, // offerAmount _addresses[2], // wantAssetId _values[0] >> 128, // wantAmount _addresses[3], // feeAssetId _values[1] & mask128, // feeAmount _values[2] >> 144 // offerNonce )); } /// @notice Approves a token transfer /// @param _assetId The address of the token to approve /// @param _spender The address of the spender to approve /// @param _amount The number of tokens to approve function approveTokenTransfer( address _assetId, address _spender, uint256 _amount ) public { _validateContractAddress(_assetId); // Some tokens have an `approve` which returns a boolean and some do not. // The ERC20 interface cannot be used here because it requires specifying // an explicit return value, and an EVM exception would be raised when calling // a token with the mismatched return value. bytes memory payload = abi.encodeWithSignature( "approve(address,uint256)", _spender, _amount ); bytes memory returnData = _callContract(_assetId, payload); // Ensure that the asset transfer succeeded _validateContractCallResult(returnData); } /// @notice Transfers tokens into the contract /// @param _user The address to transfer the tokens from /// @param _assetId The address of the token to transfer /// @param _amount The number of tokens to transfer /// @param _expectedAmount The number of tokens expected to be received, /// this may not match `_amount`, for example, tokens which have a /// proportion burnt on transfer will have a different amount received. function transferTokensIn( address _user, address _assetId, uint256 _amount, uint256 _expectedAmount ) public { _validateContractAddress(_assetId); uint256 initialBalance = tokenBalance(_assetId); // Some tokens have a `transferFrom` which returns a boolean and some do not. // The ERC20 interface cannot be used here because it requires specifying // an explicit return value, and an EVM exception would be raised when calling // a token with the mismatched return value. bytes memory payload = abi.encodeWithSignature( "transferFrom(address,address,uint256)", _user, address(this), _amount ); bytes memory returnData = _callContract(_assetId, payload); // Ensure that the asset transfer succeeded _validateContractCallResult(returnData); uint256 finalBalance = tokenBalance(_assetId); uint256 transferredAmount = finalBalance.sub(initialBalance); require(transferredAmount == _expectedAmount, "Invalid transfer"); } /// @notice Transfers tokens from the contract to a user /// @param _receivingAddress The address to transfer the tokens to /// @param _assetId The address of the token to transfer /// @param _amount The number of tokens to transfer function transferTokensOut( address _receivingAddress, address _assetId, uint256 _amount ) public { _validateContractAddress(_assetId); // Some tokens have a `transfer` which returns a boolean and some do not. // The ERC20 interface cannot be used here because it requires specifying // an explicit return value, and an EVM exception would be raised when calling // a token with the mismatched return value. bytes memory payload = abi.encodeWithSignature( "transfer(address,uint256)", _receivingAddress, _amount ); bytes memory returnData = _callContract(_assetId, payload); // Ensure that the asset transfer succeeded _validateContractCallResult(returnData); } /// @notice Returns the number of tokens owned by this contract /// @param _assetId The address of the token to query function externalBalance(address _assetId) public view returns (uint256) { if (_assetId == ETHER_ADDR) { return address(this).balance; } return tokenBalance(_assetId); } /// @notice Returns the number of tokens owned by this contract. /// @dev This will not work for Ether tokens, use `externalBalance` for /// Ether tokens. /// @param _assetId The address of the token to query function tokenBalance(address _assetId) public view returns (uint256) { return ERC20(_assetId).balanceOf(address(this)); } /// @dev Validates that the specified `_hash` was signed by the specified `_user`. /// This method supports the EIP712 specification, the older Ethereum /// signed message specification is also supported for backwards compatibility. /// @param _hash The original hash that was signed by the user /// @param _user The user who signed the hash /// @param _v The `v` component of the `_user`'s signature /// @param _r The `r` component of the `_user`'s signature /// @param _s The `s` component of the `_user`'s signature /// @param _prefixed If true, the signature will be verified /// against the Ethereum signed message specification instead of the /// EIP712 specification function validateSignature( bytes32 _hash, address _user, uint8 _v, bytes32 _r, bytes32 _s, bool _prefixed ) public pure { bytes32 eip712Hash = keccak256(abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR, _hash )); if (_prefixed) { bytes32 prefixedHash = keccak256(abi.encodePacked( "\x19Ethereum Signed Message:\n32", eip712Hash )); require(_user == ecrecover(prefixedHash, _v, _r, _s), "Invalid signature"); } else { require(_user == ecrecover(eip712Hash, _v, _r, _s), "Invalid signature"); } } /// @dev Ensures that `_address` is not the zero address /// @param _address The address to check function validateAddress(address _address) public pure { require(_address != address(0), "Invalid address"); } /// @dev Credit fillers for each fill.wantAmount,and credit the operator /// for each fill.feeAmount. See the `trade` method for param details. /// @param _values Values from `trade` function _creditFillBalances( uint256[] memory _increments, uint256[] memory _values ) private pure { // 1 + numOffers * 2 uint256 i = 1 + (_values[0] & mask8) * 2; // i + numFills * 2 uint256 end = i + ((_values[0] & mask16) >> 8) * 2; // loop fills for(i; i < end; i += 2) { uint256 fillerWantAssetIndex = (_values[i] & mask24) >> 16; uint256 wantAmount = _values[i + 1] >> 128; // credit fill.wantAmount to filler _increments[fillerWantAssetIndex] = _increments[fillerWantAssetIndex].add(wantAmount); uint256 feeAmount = _values[i] >> 128; if (feeAmount == 0) { continue; } uint256 operatorFeeAssetIndex = ((_values[i] & mask40) >> 32); // credit fill.feeAmount to operator _increments[operatorFeeAssetIndex] = _increments[operatorFeeAssetIndex].add(feeAmount); } } /// @dev Credit makers for each amount received through a matched fill. /// See the `trade` method for param details. /// @param _values Values from `trade` function _creditMakerBalances( uint256[] memory _increments, uint256[] memory _values ) private pure { uint256 i = 1; // i += numOffers * 2 i += (_values[0] & mask8) * 2; // i += numFills * 2 i += ((_values[0] & mask16) >> 8) * 2; uint256 end = _values.length; // loop matches for(i; i < end; i++) { // match.offerIndex uint256 offerIndex = _values[i] & mask8; // maker.wantAssetIndex uint256 makerWantAssetIndex = (_values[1 + offerIndex * 2] & mask24) >> 16; // match.takeAmount uint256 amount = _values[i] >> 128; // receiveAmount = match.takeAmount * offer.wantAmount / offer.offerAmount amount = amount.mul(_values[2 + offerIndex * 2] >> 128) .div(_values[2 + offerIndex * 2] & mask128); // credit maker for the amount received from the match _increments[makerWantAssetIndex] = _increments[makerWantAssetIndex].add(amount); } } /// @dev Credit the operator for each offer.feeAmount if the offer has not /// been recorded through a previous `trade` call. /// See the `trade` method for param details. /// @param _values Values from `trade` function _creditMakerFeeBalances( uint256[] memory _increments, uint256[] memory _values ) private pure { uint256 i = 1; // i + numOffers * 2 uint256 end = i + (_values[0] & mask8) * 2; // loop offers for(i; i < end; i += 2) { bool nonceTaken = ((_values[i] & mask128) >> 120) == 1; if (nonceTaken) { continue; } uint256 feeAmount = _values[i] >> 128; if (feeAmount == 0) { continue; } uint256 operatorFeeAssetIndex = (_values[i] & mask40) >> 32; // credit make.feeAmount to operator _increments[operatorFeeAssetIndex] = _increments[operatorFeeAssetIndex].add(feeAmount); } } /// @dev Deduct tokens from fillers for each fill.offerAmount /// and each fill.feeAmount. /// See the `trade` method for param details. /// @param _values Values from `trade` function _deductFillBalances( uint256[] memory _decrements, uint256[] memory _values ) private pure { // 1 + numOffers * 2 uint256 i = 1 + (_values[0] & mask8) * 2; // i + numFills * 2 uint256 end = i + ((_values[0] & mask16) >> 8) * 2; // loop fills for(i; i < end; i += 2) { uint256 fillerOfferAssetIndex = (_values[i] & mask16) >> 8; uint256 offerAmount = _values[i + 1] & mask128; // deduct fill.offerAmount from filler _decrements[fillerOfferAssetIndex] = _decrements[fillerOfferAssetIndex].add(offerAmount); uint256 feeAmount = _values[i] >> 128; if (feeAmount == 0) { continue; } // deduct fill.feeAmount from filler uint256 fillerFeeAssetIndex = (_values[i] & mask32) >> 24; _decrements[fillerFeeAssetIndex] = _decrements[fillerFeeAssetIndex].add(feeAmount); } } /// @dev Deduct tokens from makers for each offer.offerAmount /// and each offer.feeAmount if the offer has not been recorded /// through a previous `trade` call. /// See the `trade` method for param details. /// @param _values Values from `trade` function _deductMakerBalances( uint256[] memory _decrements, uint256[] memory _values ) private pure { uint256 i = 1; // i + numOffers * 2 uint256 end = i + (_values[0] & mask8) * 2; // loop offers for(i; i < end; i += 2) { bool nonceTaken = ((_values[i] & mask128) >> 120) == 1; if (nonceTaken) { continue; } uint256 makerOfferAssetIndex = (_values[i] & mask16) >> 8; uint256 offerAmount = _values[i + 1] & mask128; // deduct make.offerAmount from maker _decrements[makerOfferAssetIndex] = _decrements[makerOfferAssetIndex].add(offerAmount); uint256 feeAmount = _values[i] >> 128; if (feeAmount == 0) { continue; } // deduct make.feeAmount from maker uint256 makerFeeAssetIndex = (_values[i] & mask32) >> 24; _decrements[makerFeeAssetIndex] = _decrements[makerFeeAssetIndex].add(feeAmount); } } /// @dev Emits trade events for easier tracking /// @param _values The _values param from the trade / networkTrade method /// @param _addresses The _addresses param from the trade / networkTrade method /// @param _marketDapps The _marketDapps from BrokerV2 /// @param _forNetworkTrade Whether this is called from the networkTrade method function _emitTradeEvents( uint256[] memory _values, address[] memory _addresses, address[] memory _marketDapps, bool _forNetworkTrade ) private { uint256 i = 1; // i += numOffers * 2 i += (_values[0] & mask8) * 2; // i += numFills * 2 i += ((_values[0] & mask16) >> 8) * 2; uint256 end = _values.length; // loop matches for(i; i < end; i++) { uint256[] memory data = new uint256[](7); data[0] = _values[i] & mask8; // match.offerIndex data[1] = _values[1 + data[0] * 2] & mask8; // makerIndex data[2] = (_values[1 + data[0] * 2] & mask16) >> 8; // makerOfferAssetIndex data[3] = (_values[1 + data[0] * 2] & mask24) >> 16; // makerWantAssetIndex data[4] = _values[i] >> 128; // match.takeAmount // receiveAmount = match.takeAmount * offer.wantAmount / offer.offerAmount data[5] = data[4].mul(_values[2 + data[0] * 2] >> 128) .div(_values[2 + data[0] * 2] & mask128); // match.fillIndex for `trade`, marketDappIndex for `networkTrade` data[6] = (_values[i] & mask16) >> 8; address filler; if (_forNetworkTrade) { filler = _marketDapps[data[6]]; } else { uint256 fillerIndex = (_values[1 + data[6] * 2] & mask8); filler = _addresses[fillerIndex * 2]; } emit Trade( _addresses[data[1] * 2], // maker filler, _addresses[data[2] * 2 + 1], // makerGiveAsset data[4], // makerGiveAmount _addresses[data[3] * 2 + 1], // fillerGiveAsset data[5] // fillerGiveAmount ); } } /// @notice Executes a trade against an external market. /// @dev The initial Ether or token balance is compared with the /// balance after the trade to ensure that the appropriate amounts of /// tokens were taken and an appropriate amount received. /// The trade will fail if the number of tokens received is less than /// expected. If the number of tokens received is more than expected than /// the excess tokens are transferred to the `BrokerV2.operator`. /// @param _assetIds[0] The offerAssetId of the offer /// @param _assetIds[1] The wantAssetId of the offer /// @param _assetIds[2] The surplusAssetId /// @param _dataValues[0] The number of tokens offerred /// @param _dataValues[1] The number of tokens expected to be received /// @param _dataValues[2] Match data /// @param _marketDapps See `BrokerV2.marketDapps` /// @param _addresses Addresses from `networkTrade` function _performNetworkTrade( address[] memory _assetIds, uint256[] memory _dataValues, address[] memory _marketDapps, address[] memory _addresses ) private returns (uint256) { uint256 dappIndex = (_dataValues[2] & mask16) >> 8; validateAddress(_marketDapps[dappIndex]); MarketDapp marketDapp = MarketDapp(_marketDapps[dappIndex]); uint256[] memory funds = new uint256[](6); funds[0] = externalBalance(_assetIds[0]); // initialOfferTokenBalance funds[1] = externalBalance(_assetIds[1]); // initialWantTokenBalance if (_assetIds[2] != _assetIds[0] && _assetIds[2] != _assetIds[1]) { funds[2] = externalBalance(_assetIds[2]); // initialSurplusTokenBalance } uint256 ethValue = 0; address tokenReceiver; if (_assetIds[0] == ETHER_ADDR) { ethValue = _dataValues[0]; // offerAmount } else { tokenReceiver = marketDapp.tokenReceiver(_assetIds, _dataValues, _addresses); approveTokenTransfer( _assetIds[0], // offerAssetId tokenReceiver, _dataValues[0] // offerAmount ); } marketDapp.trade.value(ethValue)( _assetIds, _dataValues, _addresses, // use uint160 to cast `address` to `address payable` address(uint160(address(this))) // destAddress ); funds[3] = externalBalance(_assetIds[0]); // finalOfferTokenBalance funds[4] = externalBalance(_assetIds[1]); // finalWantTokenBalance if (_assetIds[2] != _assetIds[0] && _assetIds[2] != _assetIds[1]) { funds[5] = externalBalance(_assetIds[2]); // finalSurplusTokenBalance } uint256 surplusAmount = 0; // validate that the appropriate offerAmount was deducted // surplusAssetId == offerAssetId if (_assetIds[2] == _assetIds[0]) { // surplusAmount = finalOfferTokenBalance - (initialOfferTokenBalance - offerAmount) surplusAmount = funds[3].sub(funds[0].sub(_dataValues[0])); } else { // finalOfferTokenBalance == initialOfferTokenBalance - offerAmount require(funds[3] == funds[0].sub(_dataValues[0]), "Invalid offer asset balance"); } // validate that the appropriate wantAmount was credited // surplusAssetId == wantAssetId if (_assetIds[2] == _assetIds[1]) { // surplusAmount = finalWantTokenBalance - (initialWantTokenBalance + wantAmount) surplusAmount = funds[4].sub(funds[1].add(_dataValues[1])); } else { // finalWantTokenBalance == initialWantTokenBalance + wantAmount require(funds[4] == funds[1].add(_dataValues[1]), "Invalid want asset balance"); } // surplusAssetId != offerAssetId && surplusAssetId != wantAssetId if (_assetIds[2] != _assetIds[0] && _assetIds[2] != _assetIds[1]) { // surplusAmount = finalSurplusTokenBalance - initialSurplusTokenBalance surplusAmount = funds[5].sub(funds[2]); } // set the approved token amount back to zero if (_assetIds[0] != ETHER_ADDR) { approveTokenTransfer( _assetIds[0], tokenReceiver, 0 ); } return surplusAmount; } /// @dev Validates input lengths based on the expected format /// detailed in the `trade` method. /// @param _values Values from `trade` /// @param _hashes Hashes from `trade` function _validateTradeInputLengths( uint256[] memory _values, bytes32[] memory _hashes ) private pure { uint256 numOffers = _values[0] & mask8; uint256 numFills = (_values[0] & mask16) >> 8; uint256 numMatches = (_values[0] & mask24) >> 16; // Validate that bits(24..256) are zero require(_values[0] >> 24 == 0, "Invalid trade input"); // It is enforced by other checks that if a fill is present // then it must be completely filled so there must be at least one offer // and at least one match in this case. // It is possible to have one offer with no matches and no fills // but that is blocked by this check as there is no foreseeable use // case for it. require( numOffers > 0 && numFills > 0 && numMatches > 0, "Invalid trade input" ); require( _values.length == 1 + numOffers * 2 + numFills * 2 + numMatches, "Invalid _values.length" ); require( _hashes.length == (numOffers + numFills) * 2, "Invalid _hashes.length" ); } /// @dev Validates input lengths based on the expected format /// detailed in the `networkTrade` method. /// @param _values Values from `networkTrade` /// @param _hashes Hashes from `networkTrade` function _validateNetworkTradeInputLengths( uint256[] memory _values, bytes32[] memory _hashes ) private pure { uint256 numOffers = _values[0] & mask8; uint256 numFills = (_values[0] & mask16) >> 8; uint256 numMatches = (_values[0] & mask24) >> 16; // Validate that bits(24..256) are zero require(_values[0] >> 24 == 0, "Invalid networkTrade input"); // Validate that numFills is zero because the offers // should be filled against external orders require( numOffers > 0 && numMatches > 0 && numFills == 0, "Invalid networkTrade input" ); require( _values.length == 1 + numOffers * 2 + numMatches, "Invalid _values.length" ); require( _hashes.length == numOffers * 2, "Invalid _hashes.length" ); } /// @dev See the `BrokerV2.trade` method for an explanation of why offer /// uniquness is required. /// The set of offers in `_values` must be sorted such that offer nonces' /// are arranged in a strictly ascending order. /// This allows the validation of offer uniqueness to be done in O(N) time, /// with N being the number of offers. /// @param _values Values from `trade` function _validateUniqueOffers(uint256[] memory _values) private pure { uint256 numOffers = _values[0] & mask8; uint256 prevNonce; for(uint256 i = 0; i < numOffers; i++) { uint256 nonce = (_values[i * 2 + 1] & mask120) >> 56; if (i == 0) { // Set the value of the first nonce prevNonce = nonce; continue; } require(nonce > prevNonce, "Invalid offer nonces"); prevNonce = nonce; } } /// @dev Validate that for every match: /// 1. offerIndexes fall within the range of offers /// 2. fillIndexes falls within the range of fills /// 3. offer.offerAssetId == fill.wantAssetId /// 4. offer.wantAssetId == fill.offerAssetId /// 5. takeAmount > 0 /// 6. (offer.wantAmount * takeAmount) % offer.offerAmount == 0 /// @param _values Values from `trade` /// @param _addresses Addresses from `trade` function _validateMatches( uint256[] memory _values, address[] memory _addresses ) private pure { uint256 numOffers = _values[0] & mask8; uint256 numFills = (_values[0] & mask16) >> 8; uint256 i = 1 + numOffers * 2 + numFills * 2; uint256 end = _values.length; // loop matches for (i; i < end; i++) { uint256 offerIndex = _values[i] & mask8; uint256 fillIndex = (_values[i] & mask16) >> 8; require(offerIndex < numOffers, "Invalid match.offerIndex"); require(fillIndex >= numOffers && fillIndex < numOffers + numFills, "Invalid match.fillIndex"); require( _addresses[(_values[1 + offerIndex * 2] & mask8)] != _addresses[(_values[1 + fillIndex * 2] & mask8)], "offer.maker cannot be the same as fill.filler" ); uint256 makerOfferAssetIndex = (_values[1 + offerIndex * 2] & mask16) >> 8; uint256 makerWantAssetIndex = (_values[1 + offerIndex * 2] & mask24) >> 16; uint256 fillerOfferAssetIndex = (_values[1 + fillIndex * 2] & mask16) >> 8; uint256 fillerWantAssetIndex = (_values[1 + fillIndex * 2] & mask24) >> 16; require( _addresses[makerOfferAssetIndex * 2 + 1] == _addresses[fillerWantAssetIndex * 2 + 1], "offer.offerAssetId does not match fill.wantAssetId" ); require( _addresses[makerWantAssetIndex * 2 + 1] == _addresses[fillerOfferAssetIndex * 2 + 1], "offer.wantAssetId does not match fill.offerAssetId" ); // require that bits(16..128) are all zero for every match require((_values[i] & mask128) >> 16 == uint256(0), "Invalid match data"); uint256 takeAmount = _values[i] >> 128; require(takeAmount > 0, "Invalid match.takeAmount"); uint256 offerDataB = _values[2 + offerIndex * 2]; // (offer.wantAmount * takeAmount) % offer.offerAmount == 0 require( (offerDataB >> 128).mul(takeAmount).mod(offerDataB & mask128) == 0, "Invalid amounts" ); } } /// @dev Validate that for every match: /// 1. offerIndexes fall within the range of offers /// 2. _addresses[surplusAssetIndexes * 2] matches the operator address /// 3. takeAmount > 0 /// 4. (offer.wantAmount * takeAmount) % offer.offerAmount == 0 /// @param _values Values from `trade` /// @param _addresses Addresses from `trade` /// @param _operator Address of the `BrokerV2.operator` function _validateNetworkMatches( uint256[] memory _values, address[] memory _addresses, address _operator ) private pure { uint256 numOffers = _values[0] & mask8; // 1 + numOffers * 2 uint256 i = 1 + (_values[0] & mask8) * 2; uint256 end = _values.length; // loop matches for (i; i < end; i++) { uint256 offerIndex = _values[i] & mask8; uint256 surplusAssetIndex = (_values[i] & mask24) >> 16; require(offerIndex < numOffers, "Invalid match.offerIndex"); require(_addresses[surplusAssetIndex * 2] == _operator, "Invalid operator address"); uint256 takeAmount = _values[i] >> 128; require(takeAmount > 0, "Invalid match.takeAmount"); uint256 offerDataB = _values[2 + offerIndex * 2]; // (offer.wantAmount * takeAmount) % offer.offerAmount == 0 require( (offerDataB >> 128).mul(takeAmount).mod(offerDataB & mask128) == 0, "Invalid amounts" ); } } /// @dev Validate that all fills will be completely filled by the specified /// matches. See the `BrokerV2.trade` method for an explanation of why /// fills must be completely filled. /// @param _values Values from `trade` function _validateFillAmounts(uint256[] memory _values) private pure { // "filled" is used to store the sum of `takeAmount`s and `giveAmount`s. // While a fill's `offerAmount` and `wantAmount` are combined to share // a single uint256 value, each sum of `takeAmount`s and `giveAmount`s // for a fill is tracked with an individual uint256 value. // This is to prevent the verification from being vulnerable to overflow // issues. uint256[] memory filled = new uint256[](_values.length); uint256 i = 1; // i += numOffers * 2 i += (_values[0] & mask8) * 2; // i += numFills * 2 i += ((_values[0] & mask16) >> 8) * 2; uint256 end = _values.length; // loop matches for (i; i < end; i++) { uint256 offerIndex = _values[i] & mask8; uint256 fillIndex = (_values[i] & mask16) >> 8; uint256 takeAmount = _values[i] >> 128; uint256 wantAmount = _values[2 + offerIndex * 2] >> 128; uint256 offerAmount = _values[2 + offerIndex * 2] & mask128; // giveAmount = takeAmount * wantAmount / offerAmount uint256 giveAmount = takeAmount.mul(wantAmount).div(offerAmount); // (1 + fillIndex * 2) would give the index of the first part // of the data for the fill at fillIndex within `_values`, // and (2 + fillIndex * 2) would give the index of the second part filled[1 + fillIndex * 2] = filled[1 + fillIndex * 2].add(giveAmount); filled[2 + fillIndex * 2] = filled[2 + fillIndex * 2].add(takeAmount); } // numOffers i = _values[0] & mask8; // i + numFills end = i + ((_values[0] & mask16) >> 8); // loop fills for(i; i < end; i++) { require( // fill.offerAmount == (sum of given amounts for fill) _values[i * 2 + 2] & mask128 == filled[i * 2 + 1] && // fill.wantAmount == (sum of taken amounts for fill) _values[i * 2 + 2] >> 128 == filled[i * 2 + 2], "Invalid fills" ); } } /// @dev Validates that for every offer / fill /// 1. user address matches address referenced by user.offerAssetIndex /// 2. user address matches address referenced by user.wantAssetIndex /// 3. user address matches address referenced by user.feeAssetIndex /// 4. offerAssetId != wantAssetId /// 5. offerAmount > 0 && wantAmount > 0 /// 6. Specified `operator` address matches the expected `operator` address, /// 7. Specified `operator.feeAssetId` matches the offer's feeAssetId /// @param _values Values from `trade` /// @param _addresses Addresses from `trade` function _validateTradeData( uint256[] memory _values, address[] memory _addresses, address _operator ) private pure { // numOffers + numFills uint256 end = (_values[0] & mask8) + ((_values[0] & mask16) >> 8); for (uint256 i = 0; i < end; i++) { uint256 dataA = _values[i * 2 + 1]; uint256 dataB = _values[i * 2 + 2]; require( // user address == user in user.offerAssetIndex pair _addresses[(dataA & mask8) * 2] == _addresses[((dataA & mask16) >> 8) * 2], "Invalid user in user.offerAssetIndex" ); require( // user address == user in user.wantAssetIndex pair _addresses[(dataA & mask8) * 2] == _addresses[((dataA & mask24) >> 16) * 2], "Invalid user in user.wantAssetIndex" ); require( // user address == user in user.feeAssetIndex pair _addresses[(dataA & mask8) * 2] == _addresses[((dataA & mask32) >> 24) * 2], "Invalid user in user.feeAssetIndex" ); require( // offerAssetId != wantAssetId _addresses[((dataA & mask16) >> 8) * 2 + 1] != _addresses[((dataA & mask24) >> 16) * 2 + 1], "Invalid trade assets" ); require( // offerAmount > 0 && wantAmount > 0 (dataB & mask128) > 0 && (dataB >> 128) > 0, "Invalid trade amounts" ); uint256 operatorFeeAssetIndex = ((dataA & mask40) >> 32) * 2; require( _addresses[operatorFeeAssetIndex] == _operator, "Invalid operator address" ); require( _addresses[operatorFeeAssetIndex + 1] == _addresses[((dataA & mask32) >> 24) * 2 + 1], "Invalid operator fee asset ID" ); } } /// @dev Validates signatures for a set of offers or fills /// Note that the r value of the offer / fill in _hashes will be /// overwritten by the hash of that offer / fill /// @param _values Values from `trade` /// @param _hashes Hashes from `trade` /// @param _addresses Addresses from `trade` /// @param _typehash The typehash used to construct the signed hash /// @param _i The starting index to verify /// @param _end The ending index to verify /// @return An array of hash keys if _i started as 0, because only /// the hash keys of offers are needed function _validateTradeSignatures( uint256[] memory _values, bytes32[] memory _hashes, address[] memory _addresses, bytes32 _typehash, uint256 _i, uint256 _end ) private pure { for (_i; _i < _end; _i++) { uint256 dataA = _values[_i * 2 + 1]; uint256 dataB = _values[_i * 2 + 2]; bytes32 hashKey = keccak256(abi.encode( _typehash, _addresses[(dataA & mask8) * 2], // user _addresses[((dataA & mask16) >> 8) * 2 + 1], // offerAssetId dataB & mask128, // offerAmount _addresses[((dataA & mask24) >> 16) * 2 + 1], // wantAssetId dataB >> 128, // wantAmount _addresses[((dataA & mask32) >> 24) * 2 + 1], // feeAssetId dataA >> 128, // feeAmount (dataA & mask120) >> 56 // nonce )); bool prefixedSignature = ((dataA & mask56) >> 48) != 0; validateSignature( hashKey, _addresses[(dataA & mask8) * 2], // user uint8((dataA & mask48) >> 40), // The `v` component of the user's signature _hashes[_i * 2], // The `r` component of the user's signature _hashes[_i * 2 + 1], // The `s` component of the user's signature prefixedSignature ); _hashes[_i * 2] = hashKey; } } /// @dev Ensure that the address is a deployed contract /// @param _contract The address to check function _validateContractAddress(address _contract) private view { assembly { if iszero(extcodesize(_contract)) { revert(0, 0) } } } /// @dev A thin wrapper around the native `call` function, to /// validate that the contract `call` must be successful. /// See https://solidity.readthedocs.io/en/v0.5.1/050-breaking-changes.html /// for details on constructing the `_payload` /// @param _contract Address of the contract to call /// @param _payload The data to call the contract with /// @return The data returned from the contract call function _callContract( address _contract, bytes memory _payload ) private returns (bytes memory) { bool success; bytes memory returnData; (success, returnData) = _contract.call(_payload); require(success, "Contract call failed"); return returnData; } /// @dev Fix for ERC-20 tokens that do not have proper return type /// See: https://github.com/ethereum/solidity/issues/4116 /// https://medium.com/loopring-protocol/an-incompatibility-in-smart-contract-threatening-dapp-ecosystem-72b8ca5db4da /// https://github.com/sec-bit/badERC20Fix/blob/master/badERC20Fix.sol /// @param _data The data returned from a transfer call function _validateContractCallResult(bytes memory _data) private pure { require( _data.length == 0 || (_data.length == 32 && _getUint256FromBytes(_data) != 0), "Invalid contract call result" ); } /// @dev Converts data of type `bytes` into its corresponding `uint256` value /// @param _data The data in bytes /// @return The corresponding `uint256` value function _getUint256FromBytes( bytes memory _data ) private pure returns (uint256) { uint256 parsed; assembly { parsed := mload(add(_data, 32)) } return parsed; } } // File: contracts/extensions/UniswapDappV2.sol pragma solidity 0.5.12; interface UniswapRouterV2 { function WETH() external pure returns (address); function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline) external payable returns (uint[] memory amounts); function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline) external returns (uint[] memory amounts); function swapExactTokensForTokens( uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline ) external returns (uint[] memory amounts); } /// @title The DApp adapter contract for Uniswap /// @author Switcheo Network /// @notice This contract allows BrokerV2 offers to be filled by Uniswap contract UniswapDappV2 is BrokerExtension { using SafeMath for uint256; UniswapRouterV2 public router; address private constant ETHER_ADDR = address(0); constructor(address _routerAddress) public { router = UniswapRouterV2(_routerAddress); } function setRouter(address _routerAddress) external onlyOwner nonReentrant { router = UniswapRouterV2(_routerAddress); } /// @notice See Utils._performNetworkTrade for method details function tokenReceiver( address[] memory /* _assetIds */, uint256[] memory /* _dataValues */, address[] memory /* _addresses */ ) public view returns(address) { return address(this); } /// @notice See Utils._performNetworkTrade for method details function trade( address[] memory _assetIds, uint256[] memory _dataValues, address[] memory /* _addresses */, address payable _recipient ) public payable nonReentrant { // _dataValues[2] bits(24..56): delay uint256 deadline = now.add((_dataValues[2] & ~(~uint256(0) << 56)) >> 24); // give exact ETH and expect min tokens back if (_assetIds[0] == ETHER_ADDR) { address[] memory path = new address[](2); path[0] = router.WETH(); // token in path[1] = _assetIds[1]; // token out router.swapExactETHForTokens.value(_dataValues[0])( _dataValues[1], path, _recipient, deadline ); return; } Utils.transferTokensIn(msg.sender, _assetIds[0], _dataValues[0], _dataValues[0]); Utils.approveTokenTransfer( _assetIds[0], address(router), _dataValues[0] ); if (_assetIds[1] == ETHER_ADDR) { address[] memory path = new address[](2); path[0] = _assetIds[0]; // token in path[1] = router.WETH(); // token out router.swapExactTokensForETH( _dataValues[0], _dataValues[1], path, _recipient, deadline ); return; } address[] memory path = new address[](2); path[0] = _assetIds[0]; // token in path[1] = _assetIds[1]; // token out router.swapExactTokensForTokens( _dataValues[0], _dataValues[1], path, _recipient, deadline ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_routerAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"constant":true,"inputs":[],"name":"broker","outputs":[{"internalType":"contract Broker","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_brokerAddress","type":"address"}],"name":"initializeBroker","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"router","outputs":[{"internalType":"contract UniswapRouterV2","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_routerAddress","type":"address"}],"name":"setRouter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"address[]","name":"","type":"address[]"}],"name":"tokenReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address[]","name":"_assetIds","type":"address[]"},{"internalType":"uint256[]","name":"_dataValues","type":"uint256[]"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"address payable","name":"_recipient","type":"address"}],"name":"trade","outputs":[],"payable":true,"stateMutability":"payable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506040516110d63803806110d68339818101604052602081101561003357600080fd5b50516001600055600280546001600160a01b039092166001600160a01b031990921691909117905561106c8061006a6000396000f3fe6080604052600436106100555760003560e01c806324c33e4f1461005a578063422f16da1461022857806367969383146103da578063abff01101461040d578063c0d7865514610422578063f887ea4014610455575b600080fd5b34801561006657600080fd5b5061020c6004803603606081101561007d57600080fd5b810190602081018135600160201b81111561009757600080fd5b8201836020820111156100a957600080fd5b803590602001918460208302840111600160201b831117156100ca57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561011957600080fd5b82018360208201111561012b57600080fd5b803590602001918460208302840111600160201b8311171561014c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561019b57600080fd5b8201836020820111156101ad57600080fd5b803590602001918460208302840111600160201b831117156101ce57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061046a945050505050565b604080516001600160a01b039092168252519081900360200190f35b6103d86004803603608081101561023e57600080fd5b810190602081018135600160201b81111561025857600080fd5b82018360208201111561026a57600080fd5b803590602001918460208302840111600160201b8311171561028b57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156102da57600080fd5b8201836020820111156102ec57600080fd5b803590602001918460208302840111600160201b8311171561030d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561035c57600080fd5b82018360208201111561036e57600080fd5b803590602001918460208302840111600160201b8311171561038f57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b031691506104729050565b005b3480156103e657600080fd5b506103d8600480360360208110156103fd57600080fd5b50356001600160a01b0316610e03565b34801561041957600080fd5b5061020c610ecc565b34801561042e57600080fd5b506103d86004803603602081101561044557600080fd5b50356001600160a01b0316610edb565b34801561046157600080fd5b5061020c610fc7565b309392505050565b6000805460010180825584519091906104b89060189066ffffffffffffff908890600290811061049e57fe5b602002602001015116901c42610fd690919063ffffffff16565b905060006001600160a01b0316866000815181106104d257fe5b60200260200101516001600160a01b031614156107815760408051600280825260608083018452926020830190803883395050600254604080516315ab88c960e31b815290519394506001600160a01b039091169263ad5c464892506004808301926020929190829003018186803b15801561054d57600080fd5b505afa158015610561573d6000803e3d6000fd5b505050506040513d602081101561057757600080fd5b50518151829060009061058657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050866001815181106105b357fe5b6020026020010151816001815181106105c857fe5b6001600160a01b0392831660209182029290920101526002548751911690637ff36ab59088906000906105f757fe5b60200260200101518860018151811061060c57fe5b60200260200101518488876040518663ffffffff1660e01b81526004018085815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b8381101561068a578181015183820152602001610672565b50505050905001955050505050506000604051808303818588803b1580156106b157600080fd5b505af11580156106c5573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156106ef57600080fd5b8101908080516040519392919084600160201b82111561070e57600080fd5b90830190602082018581111561072357600080fd5b82518660208202830111600160201b8211171561073f57600080fd5b82525081516020918201928201910280838360005b8381101561076c578181015183820152602001610754565b50505050905001604052505050505050610da6565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e763ac1ecbfc33886000815181106107a957fe5b6020026020010151886000815181106107be57fe5b6020026020010151896000815181106107d357fe5b60200260200101516040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200182815260200194505050505060006040518083038186803b15801561084857600080fd5b505af415801561085c573d6000803e3d6000fd5b5050505073d6e266d0221a2e7909fb7f9fd45a84d217e909e76352a23bbb8760008151811061088757fe5b6020026020010151600260009054906101000a90046001600160a01b0316886000815181106108b257fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060006040518083038186803b15801561092057600080fd5b505af4158015610934573d6000803e3d6000fd5b5050505060006001600160a01b03168660018151811061095057fe5b60200260200101516001600160a01b03161415610b665760408051600280825260608083018452926020830190803883390190505090508660008151811061099457fe5b6020026020010151816000815181106109a957fe5b6001600160a01b03928316602091820292909201810191909152600254604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d6020811015610a2757600080fd5b5051815182906001908110610a3857fe5b6001600160a01b03928316602091820292909201015260025487519116906318cbafe5908890600090610a6757fe5b602002602001015188600181518110610a7c57fe5b60200260200101518488876040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610b00578181015183820152602001610ae8565b505050509050019650505050505050600060405180830381600087803b158015610b2957600080fd5b505af1158015610b3d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156106ef57600080fd5b604080516002808252606080830184529260208301908038833901905050905086600081518110610b9357fe5b602002602001015181600081518110610ba857fe5b60200260200101906001600160a01b031690816001600160a01b03168152505086600181518110610bd557fe5b602002602001015181600181518110610bea57fe5b6001600160a01b03928316602091820292909201015260025487519116906338ed1739908890600090610c1957fe5b602002602001015188600181518110610c2e57fe5b60200260200101518488876040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610cb2578181015183820152602001610c9a565b505050509050019650505050505050600060405180830381600087803b158015610cdb57600080fd5b505af1158015610cef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610d1857600080fd5b8101908080516040519392919084600160201b821115610d3757600080fd5b908301906020820185811115610d4c57600080fd5b82518660208202830111600160201b82111715610d6857600080fd5b82525081516020918201928201910280838360005b83811015610d95578181015183820152602001610d7d565b505050509050016040525050505050505b6000548114610dfc576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050505050565b6001600160a01b038116610e57576040805162461bcd60e51b8152602060048201526016602482015275496e76616c6964205f62726f6b65724164647265737360501b604482015290519081900360640190fd5b6001546001600160a01b031615610eaa576040805162461bcd60e51b8152602060048201526012602482015271109c9bdad95c88185b1c9958591e481cd95d60721b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b60015460408051638da5cb5b60e01b8152905133926001600160a01b031691638da5cb5b9160048083019260209291908290030181600087803b158015610f2157600080fd5b505af1158015610f35573d6000803e3d6000fd5b505050506040513d6020811015610f4b57600080fd5b50516001600160a01b031614610f9d576040805162461bcd60e51b815260206004820152601260248201527124b73b30b634b21036b9b39739b2b73232b960711b604482015290519081900360640190fd5b6000805460010190819055600280546001600160a01b0319166001600160a01b0384161790555050565b6002546001600160a01b031681565b600082820183811015611030576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b939250505056fea265627a7a723158206c72b72fd0e7faef38e669d24296f2fc052e24b5e9a60cc376c8009b6ef5e30364736f6c634300050c00320000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Deployed Bytecode
0x6080604052600436106100555760003560e01c806324c33e4f1461005a578063422f16da1461022857806367969383146103da578063abff01101461040d578063c0d7865514610422578063f887ea4014610455575b600080fd5b34801561006657600080fd5b5061020c6004803603606081101561007d57600080fd5b810190602081018135600160201b81111561009757600080fd5b8201836020820111156100a957600080fd5b803590602001918460208302840111600160201b831117156100ca57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561011957600080fd5b82018360208201111561012b57600080fd5b803590602001918460208302840111600160201b8311171561014c57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561019b57600080fd5b8201836020820111156101ad57600080fd5b803590602001918460208302840111600160201b831117156101ce57600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955061046a945050505050565b604080516001600160a01b039092168252519081900360200190f35b6103d86004803603608081101561023e57600080fd5b810190602081018135600160201b81111561025857600080fd5b82018360208201111561026a57600080fd5b803590602001918460208302840111600160201b8311171561028b57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b8111156102da57600080fd5b8201836020820111156102ec57600080fd5b803590602001918460208302840111600160201b8311171561030d57600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295949360208101935035915050600160201b81111561035c57600080fd5b82018360208201111561036e57600080fd5b803590602001918460208302840111600160201b8311171561038f57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550505090356001600160a01b031691506104729050565b005b3480156103e657600080fd5b506103d8600480360360208110156103fd57600080fd5b50356001600160a01b0316610e03565b34801561041957600080fd5b5061020c610ecc565b34801561042e57600080fd5b506103d86004803603602081101561044557600080fd5b50356001600160a01b0316610edb565b34801561046157600080fd5b5061020c610fc7565b309392505050565b6000805460010180825584519091906104b89060189066ffffffffffffff908890600290811061049e57fe5b602002602001015116901c42610fd690919063ffffffff16565b905060006001600160a01b0316866000815181106104d257fe5b60200260200101516001600160a01b031614156107815760408051600280825260608083018452926020830190803883395050600254604080516315ab88c960e31b815290519394506001600160a01b039091169263ad5c464892506004808301926020929190829003018186803b15801561054d57600080fd5b505afa158015610561573d6000803e3d6000fd5b505050506040513d602081101561057757600080fd5b50518151829060009061058657fe5b60200260200101906001600160a01b031690816001600160a01b031681525050866001815181106105b357fe5b6020026020010151816001815181106105c857fe5b6001600160a01b0392831660209182029290920101526002548751911690637ff36ab59088906000906105f757fe5b60200260200101518860018151811061060c57fe5b60200260200101518488876040518663ffffffff1660e01b81526004018085815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b8381101561068a578181015183820152602001610672565b50505050905001955050505050506000604051808303818588803b1580156106b157600080fd5b505af11580156106c5573d6000803e3d6000fd5b50505050506040513d6000823e601f3d908101601f1916820160405260208110156106ef57600080fd5b8101908080516040519392919084600160201b82111561070e57600080fd5b90830190602082018581111561072357600080fd5b82518660208202830111600160201b8211171561073f57600080fd5b82525081516020918201928201910280838360005b8381101561076c578181015183820152602001610754565b50505050905001604052505050505050610da6565b73d6e266d0221a2e7909fb7f9fd45a84d217e909e763ac1ecbfc33886000815181106107a957fe5b6020026020010151886000815181106107be57fe5b6020026020010151896000815181106107d357fe5b60200260200101516040518563ffffffff1660e01b815260040180856001600160a01b03166001600160a01b03168152602001846001600160a01b03166001600160a01b0316815260200183815260200182815260200194505050505060006040518083038186803b15801561084857600080fd5b505af415801561085c573d6000803e3d6000fd5b5050505073d6e266d0221a2e7909fb7f9fd45a84d217e909e76352a23bbb8760008151811061088757fe5b6020026020010151600260009054906101000a90046001600160a01b0316886000815181106108b257fe5b60200260200101516040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b03168152602001836001600160a01b03166001600160a01b03168152602001828152602001935050505060006040518083038186803b15801561092057600080fd5b505af4158015610934573d6000803e3d6000fd5b5050505060006001600160a01b03168660018151811061095057fe5b60200260200101516001600160a01b03161415610b665760408051600280825260608083018452926020830190803883390190505090508660008151811061099457fe5b6020026020010151816000815181106109a957fe5b6001600160a01b03928316602091820292909201810191909152600254604080516315ab88c960e31b81529051919093169263ad5c4648926004808301939192829003018186803b1580156109fd57600080fd5b505afa158015610a11573d6000803e3d6000fd5b505050506040513d6020811015610a2757600080fd5b5051815182906001908110610a3857fe5b6001600160a01b03928316602091820292909201015260025487519116906318cbafe5908890600090610a6757fe5b602002602001015188600181518110610a7c57fe5b60200260200101518488876040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610b00578181015183820152602001610ae8565b505050509050019650505050505050600060405180830381600087803b158015610b2957600080fd5b505af1158015610b3d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156106ef57600080fd5b604080516002808252606080830184529260208301908038833901905050905086600081518110610b9357fe5b602002602001015181600081518110610ba857fe5b60200260200101906001600160a01b031690816001600160a01b03168152505086600181518110610bd557fe5b602002602001015181600181518110610bea57fe5b6001600160a01b03928316602091820292909201015260025487519116906338ed1739908890600090610c1957fe5b602002602001015188600181518110610c2e57fe5b60200260200101518488876040518663ffffffff1660e01b81526004018086815260200185815260200180602001846001600160a01b03166001600160a01b03168152602001838152602001828103825285818151815260200191508051906020019060200280838360005b83811015610cb2578181015183820152602001610c9a565b505050509050019650505050505050600060405180830381600087803b158015610cdb57600080fd5b505af1158015610cef573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015610d1857600080fd5b8101908080516040519392919084600160201b821115610d3757600080fd5b908301906020820185811115610d4c57600080fd5b82518660208202830111600160201b82111715610d6857600080fd5b82525081516020918201928201910280838360005b83811015610d95578181015183820152602001610d7d565b505050509050016040525050505050505b6000548114610dfc576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b5050505050565b6001600160a01b038116610e57576040805162461bcd60e51b8152602060048201526016602482015275496e76616c6964205f62726f6b65724164647265737360501b604482015290519081900360640190fd5b6001546001600160a01b031615610eaa576040805162461bcd60e51b8152602060048201526012602482015271109c9bdad95c88185b1c9958591e481cd95d60721b604482015290519081900360640190fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b60015460408051638da5cb5b60e01b8152905133926001600160a01b031691638da5cb5b9160048083019260209291908290030181600087803b158015610f2157600080fd5b505af1158015610f35573d6000803e3d6000fd5b505050506040513d6020811015610f4b57600080fd5b50516001600160a01b031614610f9d576040805162461bcd60e51b815260206004820152601260248201527124b73b30b634b21036b9b39739b2b73232b960711b604482015290519081900360640190fd5b6000805460010190819055600280546001600160a01b0319166001600160a01b0384161790555050565b6002546001600160a01b031681565b600082820183811015611030576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b939250505056fea265627a7a723158206c72b72fd0e7faef38e669d24296f2fc052e24b5e9a60cc376c8009b6ef5e30364736f6c634300050c0032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
-----Decoded View---------------
Arg [0] : _routerAddress (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Deployed Bytecode Sourcemap
58205:2682:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;58701:262;;8:9:-1;5:2;;;30:1;27;20:12;5:2;58701:262:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;58701:262:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;58701:262:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;58701:262:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;58701:262:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;58701:262:0;;;;;;;;-1:-1:-1;58701:262:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;58701:262:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;58701:262:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;58701:262:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;58701:262:0;;;;;;;;-1:-1:-1;58701:262:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;58701:262:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;58701:262:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;58701:262:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;58701:262:0;;-1:-1:-1;58701:262:0;;-1:-1:-1;;;;;58701:262:0:i;:::-;;;;-1:-1:-1;;;;;58701:262:0;;;;;;;;;;;;;;59038:1846;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;59038:1846:0;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;59038:1846:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;59038:1846:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;59038:1846:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;59038:1846:0;;;;;;;;-1:-1:-1;59038:1846:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;59038:1846:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;59038:1846:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;59038:1846:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;59038:1846:0;;;;;;;;-1:-1:-1;59038:1846:0;;-1:-1:-1;;;;;5:28;;2:2;;;46:1;43;36:12;2:2;59038:1846:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;59038:1846:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;59038:1846:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;59038:1846:0;;-1:-1:-1;;;59038:1846:0;;-1:-1:-1;;;;;59038:1846:0;;-1:-1:-1;59038:1846:0;;-1:-1:-1;59038:1846:0:i;:::-;;5826:254;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5826:254:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5826:254:0;-1:-1:-1;;;;;5826:254:0;;:::i;5561:20::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5561:20:0;;;:::i;58492:134::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;58492:134:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58492:134:0;-1:-1:-1;;;;;58492:134:0;;:::i;58289:29::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;58289:29:0;;;:::i;58701:262::-;58950:4;58701:262;;;;;:::o;59038:1846::-;5066:13;:18;;5083:1;5066:18;;;;59363:14;;5066:18;;:13;59354:54;;59405:2;;59380:20;;59363:11;;59375:1;;59363:14;;;;;;;;;;;;:37;59362:45;;59354:3;:7;;:54;;;;:::i;:::-;59335:73;;58371:1;-1:-1:-1;;;;;59479:26:0;:9;59489:1;59479:12;;;;;;;;;;;;;;-1:-1:-1;;;;;59479:26:0;;59475:414;;;59546:16;;;59560:1;59546:16;;;59522:21;59546:16;;;;;59522:21;59546:16;;;;;105:10:-1;59546:16:0;88:34:-1;-1:-1;;59587:6:0;;:13;;;-1:-1:-1;;;59587:13:0;;;;59522:40;;-1:-1:-1;;;;;;59587:6:0;;;;:11;;-1:-1:-1;59587:13:0;;;;;;;;;;;;;;:6;:13;;;5:2:-1;;;;30:1;27;20:12;5:2;59587:13:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59587:13:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;59587:13:0;59577:7;;:4;;59582:1;;59577:7;;;;;;;;;:23;-1:-1:-1;;;;;59577:23:0;;;-1:-1:-1;;;;;59577:23:0;;;;;59637:9;59647:1;59637:12;;;;;;;;;;;;;;59627:4;59632:1;59627:7;;;;;;;;-1:-1:-1;;;;;59627:22:0;;;:7;;;;;;;;;:22;59679:6;;59714:14;;59679:6;;;:28;;59714:11;;59679:6;;59714:14;;;;;;;;;;59748:11;59760:1;59748:14;;;;;;;;;;;;;;59781:4;59804:10;59833:8;59679:177;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;59679:177:0;-1:-1:-1;;;;;59679:177:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;59679:177:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59679:177:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59679:177:0;;;;;;;39:16:-1;36:1;17:17;2:54;101:4;59679:177:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;59679:177:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;59679:177:0;;421:4:-1;412:14;;;;59679:177:0;;;;;412:14:-1;59679:177:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;59679:177:0;;;;;;;;;;;;59871:7;;;;59475:414;59901:5;:22;59924:10;59936:9;59946:1;59936:12;;;;;;;;;;;;;;59950:11;59962:1;59950:14;;;;;;;;;;;;;;59966:11;59978:1;59966:14;;;;;;;;;;;;;;59901:80;;;;;;;;;;;;;-1:-1:-1;;;;;59901:80:0;-1:-1:-1;;;;;59901:80:0;;;;;;-1:-1:-1;;;;;59901:80:0;-1:-1:-1;;;;;59901:80:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59901:80:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59901:80:0;;;;59992:5;:26;60033:9;60043:1;60033:12;;;;;;;;;;;;;;60068:6;;;;;;;;;-1:-1:-1;;;;;60068:6:0;60090:11;60102:1;60090:14;;;;;;;;;;;;;;59992:123;;;;;;;;;;;;;-1:-1:-1;;;;;59992:123:0;-1:-1:-1;;;;;59992:123:0;;;;;;-1:-1:-1;;;;;59992:123:0;-1:-1:-1;;;;;59992:123:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;59992:123:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;59992:123:0;;;;58371:1;-1:-1:-1;;;;;60132:26:0;:9;60142:1;60132:12;;;;;;;;;;;;;;-1:-1:-1;;;;;60132:26:0;;60128:425;;;60199:16;;;60213:1;60199:16;;;60175:21;60199:16;;;;;60175:21;60199:16;;;;;105:10:-1;60199:16:0;88:34:-1;136:17;;-1:-1;60199:16:0;60175:40;;60240:9;60250:1;60240:12;;;;;;;;;;;;;;60230:4;60235:1;60230:7;;;;;;;;-1:-1:-1;;;;;60230:22:0;;;:7;;;;;;;;;;:22;;;;60289:6;;:13;;;-1:-1:-1;;;60289:13:0;;;;:6;;;;;:11;;:13;;;;;60230:7;;60289:13;;;;;:6;:13;;;5:2:-1;;;;30:1;27;20:12;5:2;60289:13:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60289:13:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;60289:13:0;60279:7;;:4;;60284:1;;60279:7;;;;;;-1:-1:-1;;;;;60279:23:0;;;:7;;;;;;;;;:23;60332:6;;60379:14;;60332:6;;;:28;;60379:11;;60332:6;;60379:14;;;;;;;;;;60412:11;60424:1;60412:14;;;;;;;;;;;;;;60445:4;60468:10;60497:8;60332:188;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;60332:188:0;-1:-1:-1;;;;;60332:188:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;60332:188:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60332:188:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60332:188:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;60332:188:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;60128:425:0;60589:16;;;60603:1;60589:16;;;60565:21;60589:16;;;;;60565:21;60589:16;;;;;105:10:-1;60589:16:0;88:34:-1;136:17;;-1:-1;60589:16:0;60565:40;;60626:9;60636:1;60626:12;;;;;;;;;;;;;;60616:4;60621:1;60616:7;;;;;;;;;;;;;:22;-1:-1:-1;;;;;60616:22:0;;;-1:-1:-1;;;;;60616:22:0;;;;;60671:9;60681:1;60671:12;;;;;;;;;;;;;;60661:4;60666:1;60661:7;;;;;;;;-1:-1:-1;;;;;60661:22:0;;;:7;;;;;;;;;:22;60709:6;;60755:14;;60709:6;;;:31;;60755:11;;60709:6;;60755:14;;;;;;;;;;60784:11;60796:1;60784:14;;;;;;;;;;;;;;60813:4;60832:10;60857:8;60709:167;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;60709:167:0;-1:-1:-1;;;;;60709:167:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;60709:167:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;60709:167:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;60709:167:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;60709:167:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;60709:167:0;;;;;;;;;;;;;-1:-1:-1;;;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;60709:167:0;;421:4:-1;412:14;;;;60709:167:0;;;;;412:14:-1;60709:167:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;60709:167:0;;;;;;;;;;;;5142:1;;;5178:13;;5162:12;:29;5154:73;;;;;-1:-1:-1;;;5154:73:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;59038:1846;;;;;:::o;5826:254::-;-1:-1:-1;;;;;5904:28:0;;5896:63;;;;;-1:-1:-1;;;5896:63:0;;;;;;;;;;;;-1:-1:-1;;;5896:63:0;;;;;;;;;;;;;;;5986:6;;-1:-1:-1;;;;;5986:6:0;5978:29;5970:60;;;;;-1:-1:-1;;;5970:60:0;;;;;;;;;;;;-1:-1:-1;;;5970:60:0;;;;;;;;;;;;;;;6041:6;:31;;-1:-1:-1;;;;;;6041:31:0;-1:-1:-1;;;;;6041:31:0;;;;;;;;;;5826:254::o;5561:20::-;;;-1:-1:-1;;;;;5561:20:0;;:::o;58492:134::-;5747:6;;:14;;;-1:-1:-1;;;5747:14:0;;;;5765:10;;-1:-1:-1;;;;;5747:6:0;;:12;;:14;;;;;;;;;;;;;;:6;;:14;;;5:2:-1;;;;30:1;27;20:12;5:2;5747:14:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;5747:14:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;5747:14:0;-1:-1:-1;;;;;5747:28:0;;5739:59;;;;;-1:-1:-1;;;5739:59:0;;;;;;;;;;;;-1:-1:-1;;;5739:59:0;;;;;;;;;;;;;;;5066:13;:18;;5083:1;5066:18;;;;;58578:6;:40;;-1:-1:-1;;;;;;58578:40:0;-1:-1:-1;;;;;58578:40:0;;;;;5809:1;58492:134;:::o;58289:29::-;;;-1:-1:-1;;;;;58289:29:0;;:::o;903:181::-;961:7;993:5;;;1017:6;;;;1009:46;;;;;-1:-1:-1;;;1009:46:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;1075:1;903:181;-1:-1:-1;;;903:181:0:o
Swarm Source
bzzr://6c72b72fd0e7faef38e669d24296f2fc052e24b5e9a60cc376c8009b6ef5e303
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.