Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x61063561 | 13113276 | 1054 days ago | IN | Create: ExchangeTokens | 0 ETH | 0.01927111 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ExchangeTokens
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2021-08-28 */ // SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.7.0; pragma experimental ABIEncoderV2; // File: contracts/lib/ERC20SafeTransfer.sol // Copyright 2017 Loopring Technology Limited. /// @title ERC20 safe transfer /// @dev see https://github.com/sec-bit/badERC20Fix /// @author Brecht Devos - <[email protected]> library ERC20SafeTransfer { function safeTransferAndVerify( address token, address to, uint value ) internal { safeTransferWithGasLimitAndVerify( token, to, value, gasleft() ); } function safeTransfer( address token, address to, uint value ) internal returns (bool) { return safeTransferWithGasLimit( token, to, value, gasleft() ); } function safeTransferWithGasLimitAndVerify( address token, address to, uint value, uint gasLimit ) internal { require( safeTransferWithGasLimit(token, to, value, gasLimit), "TRANSFER_FAILURE" ); } function safeTransferWithGasLimit( address token, address to, uint value, uint gasLimit ) internal returns (bool) { // A transfer is successful when 'call' is successful and depending on the token: // - No value is returned: we assume a revert when the transfer failed (i.e. 'call' returns false) // - A single boolean is returned: this boolean needs to be true (non-zero) // bytes4(keccak256("transfer(address,uint256)")) = 0xa9059cbb bytes memory callData = abi.encodeWithSelector( bytes4(0xa9059cbb), to, value ); (bool success, ) = token.call{gas: gasLimit}(callData); return checkReturnValue(success); } function safeTransferFromAndVerify( address token, address from, address to, uint value ) internal { safeTransferFromWithGasLimitAndVerify( token, from, to, value, gasleft() ); } function safeTransferFrom( address token, address from, address to, uint value ) internal returns (bool) { return safeTransferFromWithGasLimit( token, from, to, value, gasleft() ); } function safeTransferFromWithGasLimitAndVerify( address token, address from, address to, uint value, uint gasLimit ) internal { bool result = safeTransferFromWithGasLimit( token, from, to, value, gasLimit ); require(result, "TRANSFER_FAILURE"); } function safeTransferFromWithGasLimit( address token, address from, address to, uint value, uint gasLimit ) internal returns (bool) { // A transferFrom is successful when 'call' is successful and depending on the token: // - No value is returned: we assume a revert when the transfer failed (i.e. 'call' returns false) // - A single boolean is returned: this boolean needs to be true (non-zero) // bytes4(keccak256("transferFrom(address,address,uint256)")) = 0x23b872dd bytes memory callData = abi.encodeWithSelector( bytes4(0x23b872dd), from, to, value ); (bool success, ) = token.call{gas: gasLimit}(callData); return checkReturnValue(success); } function checkReturnValue( bool success ) internal pure returns (bool) { // A transfer/transferFrom is successful when 'call' is successful and depending on the token: // - No value is returned: we assume a revert when the transfer failed (i.e. 'call' returns false) // - A single boolean is returned: this boolean needs to be true (non-zero) if (success) { assembly { switch returndatasize() // Non-standard ERC20: nothing is returned so if 'call' was successful we assume the transfer succeeded case 0 { success := 1 } // Standard ERC20: a single boolean value is returned which needs to be true case 32 { returndatacopy(0, 0, 32) success := mload(0) } // None of the above: not successful default { success := 0 } } } return success; } } // File: contracts/lib/MathUint.sol // Copyright 2017 Loopring Technology Limited. /// @title Utility Functions for uint /// @author Daniel Wang - <[email protected]> library MathUint { using MathUint for uint; function mul( uint a, uint b ) internal pure returns (uint c) { c = a * b; require(a == 0 || c / a == b, "MUL_OVERFLOW"); } function sub( uint a, uint b ) internal pure returns (uint) { require(b <= a, "SUB_UNDERFLOW"); return a - b; } function add( uint a, uint b ) internal pure returns (uint c) { c = a + b; require(c >= a, "ADD_OVERFLOW"); } function add64( uint64 a, uint64 b ) internal pure returns (uint64 c) { c = a + b; require(c >= a, "ADD_OVERFLOW"); } } // File: contracts/core/iface/IAgentRegistry.sol // Copyright 2017 Loopring Technology Limited. interface IAgent{} abstract contract IAgentRegistry { /// @dev Returns whether an agent address is an agent of an account owner /// @param owner The account owner. /// @param agent The agent address /// @return True if the agent address is an agent for the account owner, else false function isAgent( address owner, address agent ) external virtual view returns (bool); /// @dev Returns whether an agent address is an agent of all account owners /// @param owners The account owners. /// @param agent The agent address /// @return True if the agent address is an agent for the account owner, else false function isAgent( address[] calldata owners, address agent ) external virtual view returns (bool); /// @dev Returns whether an agent address is a universal agent. /// @param agent The agent address /// @return True if the agent address is a universal agent, else false function isUniversalAgent(address agent) public virtual view returns (bool); } // File: contracts/lib/Ownable.sol // Copyright 2017 Loopring Technology Limited. /// @title Ownable /// @author Brecht Devos - <[email protected]> /// @dev The Ownable contract has an owner address, and provides basic /// authorization control functions, this simplifies the implementation of /// "user permissions". contract Ownable { address public owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /// @dev The Ownable constructor sets the original `owner` of the contract /// to the sender. constructor() { owner = msg.sender; } /// @dev Throws if called by any account other than the owner. modifier onlyOwner() { require(msg.sender == owner, "UNAUTHORIZED"); _; } /// @dev Allows the current owner to transfer control of the contract to a /// new owner. /// @param newOwner The address to transfer ownership to. function transferOwnership( address newOwner ) public virtual onlyOwner { require(newOwner != address(0), "ZERO_ADDRESS"); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } function renounceOwnership() public onlyOwner { emit OwnershipTransferred(owner, address(0)); owner = address(0); } } // File: contracts/lib/Claimable.sol // Copyright 2017 Loopring Technology Limited. /// @title Claimable /// @author Brecht Devos - <[email protected]> /// @dev Extension for the Ownable contract, where the ownership needs /// to be claimed. This allows the new owner to accept the transfer. contract Claimable is Ownable { address public pendingOwner; /// @dev Modifier throws if called by any account other than the pendingOwner. modifier onlyPendingOwner() { require(msg.sender == pendingOwner, "UNAUTHORIZED"); _; } /// @dev Allows the current owner to set the pendingOwner address. /// @param newOwner The address to transfer ownership to. function transferOwnership( address newOwner ) public override onlyOwner { require(newOwner != address(0) && newOwner != owner, "INVALID_ADDRESS"); pendingOwner = newOwner; } /// @dev Allows the pendingOwner address to finalize the transfer. function claimOwnership() public onlyPendingOwner { emit OwnershipTransferred(owner, pendingOwner); owner = pendingOwner; pendingOwner = address(0); } } // File: contracts/core/iface/IBlockVerifier.sol // Copyright 2017 Loopring Technology Limited. /// @title IBlockVerifier /// @author Brecht Devos - <[email protected]> abstract contract IBlockVerifier is Claimable { // -- Events -- event CircuitRegistered( uint8 indexed blockType, uint16 blockSize, uint8 blockVersion ); event CircuitDisabled( uint8 indexed blockType, uint16 blockSize, uint8 blockVersion ); // -- Public functions -- /// @dev Sets the verifying key for the specified circuit. /// Every block permutation needs its own circuit and thus its own set of /// verification keys. Only a limited number of block sizes per block /// type are supported. /// @param blockType The type of the block /// @param blockSize The number of requests handled in the block /// @param blockVersion The block version (i.e. which circuit version needs to be used) /// @param vk The verification key function registerCircuit( uint8 blockType, uint16 blockSize, uint8 blockVersion, uint[18] calldata vk ) external virtual; /// @dev Disables the use of the specified circuit. /// @param blockType The type of the block /// @param blockSize The number of requests handled in the block /// @param blockVersion The block version (i.e. which circuit version needs to be used) function disableCircuit( uint8 blockType, uint16 blockSize, uint8 blockVersion ) external virtual; /// @dev Verifies blocks with the given public data and proofs. /// Verifying a block makes sure all requests handled in the block /// are correctly handled by the operator. /// @param blockType The type of block /// @param blockSize The number of requests handled in the block /// @param blockVersion The block version (i.e. which circuit version needs to be used) /// @param publicInputs The hash of all the public data of the blocks /// @param proofs The ZK proofs proving that the blocks are correct /// @return True if the block is valid, false otherwise function verifyProofs( uint8 blockType, uint16 blockSize, uint8 blockVersion, uint[] calldata publicInputs, uint[] calldata proofs ) external virtual view returns (bool); /// @dev Checks if a circuit with the specified parameters is registered. /// @param blockType The type of the block /// @param blockSize The number of requests handled in the block /// @param blockVersion The block version (i.e. which circuit version needs to be used) /// @return True if the circuit is registered, false otherwise function isCircuitRegistered( uint8 blockType, uint16 blockSize, uint8 blockVersion ) external virtual view returns (bool); /// @dev Checks if a circuit can still be used to commit new blocks. /// @param blockType The type of the block /// @param blockSize The number of requests handled in the block /// @param blockVersion The block version (i.e. which circuit version needs to be used) /// @return True if the circuit is enabled, false otherwise function isCircuitEnabled( uint8 blockType, uint16 blockSize, uint8 blockVersion ) external virtual view returns (bool); } // File: contracts/core/iface/IDepositContract.sol // Copyright 2017 Loopring Technology Limited. /// @title IDepositContract. /// @dev Contract storing and transferring funds for an exchange. /// /// ERC1155 tokens can be supported by registering pseudo token addresses calculated /// as `address(keccak256(real_token_address, token_params))`. Then the custom /// deposit contract can look up the real token address and paramsters with the /// pseudo token address before doing the transfers. /// @author Brecht Devos - <[email protected]> interface IDepositContract { /// @dev Returns if a token is suppoprted by this contract. function isTokenSupported(address token) external view returns (bool); /// @dev Transfers tokens from a user to the exchange. This function will /// be called when a user deposits funds to the exchange. /// In a simple implementation the funds are simply stored inside the /// deposit contract directly. More advanced implementations may store the funds /// in some DeFi application to earn interest, so this function could directly /// call the necessary functions to store the funds there. /// /// This function needs to throw when an error occurred! /// /// This function can only be called by the exchange. /// /// @param from The address of the account that sends the tokens. /// @param token The address of the token to transfer (`0x0` for ETH). /// @param amount The amount of tokens to transfer. /// @param extraData Opaque data that can be used by the contract to handle the deposit /// @return amountReceived The amount to deposit to the user's account in the Merkle tree function deposit( address from, address token, uint96 amount, bytes calldata extraData ) external payable returns (uint96 amountReceived); /// @dev Transfers tokens from the exchange to a user. This function will /// be called when a withdrawal is done for a user on the exchange. /// In the simplest implementation the funds are simply stored inside the /// deposit contract directly so this simply transfers the requested tokens back /// to the user. More advanced implementations may store the funds /// in some DeFi application to earn interest so the function would /// need to get those tokens back from the DeFi application first before they /// can be transferred to the user. /// /// This function needs to throw when an error occurred! /// /// This function can only be called by the exchange. /// /// @param from The address from which 'amount' tokens are transferred. /// @param to The address to which 'amount' tokens are transferred. /// @param token The address of the token to transfer (`0x0` for ETH). /// @param amount The amount of tokens transferred. /// @param extraData Opaque data that can be used by the contract to handle the withdrawal function withdraw( address from, address to, address token, uint amount, bytes calldata extraData ) external payable; /// @dev Transfers tokens (ETH not supported) for a user using the allowance set /// for the exchange. This way the approval can be used for all functionality (and /// extended functionality) of the exchange. /// Should NOT be used to deposit/withdraw user funds, `deposit`/`withdraw` /// should be used for that as they will contain specialised logic for those operations. /// This function can be called by the exchange to transfer onchain funds of users /// necessary for Agent functionality. /// /// This function needs to throw when an error occurred! /// /// This function can only be called by the exchange. /// /// @param from The address of the account that sends the tokens. /// @param to The address to which 'amount' tokens are transferred. /// @param token The address of the token to transfer (ETH is and cannot be suppported). /// @param amount The amount of tokens transferred. function transfer( address from, address to, address token, uint amount ) external payable; /// @dev Checks if the given address is used for depositing ETH or not. /// Is used while depositing to send the correct ETH amount to the deposit contract. /// /// Note that 0x0 is always registered for deposting ETH when the exchange is created! /// This function allows additional addresses to be used for depositing ETH, the deposit /// contract can implement different behaviour based on the address value. /// /// @param addr The address to check /// @return True if the address is used for depositing ETH, else false. function isETH(address addr) external view returns (bool); } // File: contracts/core/iface/ILoopringV3.sol // Copyright 2017 Loopring Technology Limited. /// @title ILoopringV3 /// @author Brecht Devos - <[email protected]> /// @author Daniel Wang - <[email protected]> abstract contract ILoopringV3 is Claimable { // == Events == event ExchangeStakeDeposited(address exchangeAddr, uint amount); event ExchangeStakeWithdrawn(address exchangeAddr, uint amount); event ExchangeStakeBurned(address exchangeAddr, uint amount); event SettingsUpdated(uint time); // == Public Variables == mapping (address => uint) internal exchangeStake; uint public totalStake; address public blockVerifierAddress; uint public forcedWithdrawalFee; uint public tokenRegistrationFeeLRCBase; uint public tokenRegistrationFeeLRCDelta; uint8 public protocolTakerFeeBips; uint8 public protocolMakerFeeBips; address payable public protocolFeeVault; // == Public Functions == /// @dev Returns the LRC token address /// @return the LRC token address function lrcAddress() external view virtual returns (address); /// @dev Updates the global exchange settings. /// This function can only be called by the owner of this contract. /// /// Warning: these new values will be used by existing and /// new Loopring exchanges. function updateSettings( address payable _protocolFeeVault, // address(0) not allowed address _blockVerifierAddress, // address(0) not allowed uint _forcedWithdrawalFee ) external virtual; /// @dev Updates the global protocol fee settings. /// This function can only be called by the owner of this contract. /// /// Warning: these new values will be used by existing and /// new Loopring exchanges. function updateProtocolFeeSettings( uint8 _protocolTakerFeeBips, uint8 _protocolMakerFeeBips ) external virtual; /// @dev Gets the amount of staked LRC for an exchange. /// @param exchangeAddr The address of the exchange /// @return stakedLRC The amount of LRC function getExchangeStake( address exchangeAddr ) public virtual view returns (uint stakedLRC); /// @dev Burns a certain amount of staked LRC for a specific exchange. /// This function is meant to be called only from exchange contracts. /// @return burnedLRC The amount of LRC burned. If the amount is greater than /// the staked amount, all staked LRC will be burned. function burnExchangeStake( uint amount ) external virtual returns (uint burnedLRC); /// @dev Stakes more LRC for an exchange. /// @param exchangeAddr The address of the exchange /// @param amountLRC The amount of LRC to stake /// @return stakedLRC The total amount of LRC staked for the exchange function depositExchangeStake( address exchangeAddr, uint amountLRC ) external virtual returns (uint stakedLRC); /// @dev Withdraws a certain amount of staked LRC for an exchange to the given address. /// This function is meant to be called only from within exchange contracts. /// @param recipient The address to receive LRC /// @param requestedAmount The amount of LRC to withdraw /// @return amountLRC The amount of LRC withdrawn function withdrawExchangeStake( address recipient, uint requestedAmount ) external virtual returns (uint amountLRC); /// @dev Gets the protocol fee values for an exchange. /// @return takerFeeBips The protocol taker fee /// @return makerFeeBips The protocol maker fee function getProtocolFeeValues( ) public virtual view returns ( uint8 takerFeeBips, uint8 makerFeeBips ); } // File: contracts/core/iface/ExchangeData.sol // Copyright 2017 Loopring Technology Limited. /// @title ExchangeData /// @dev All methods in this lib are internal, therefore, there is no need /// to deploy this library independently. /// @author Daniel Wang - <[email protected]> /// @author Brecht Devos - <[email protected]> library ExchangeData { // -- Enums -- enum TransactionType { NOOP, DEPOSIT, WITHDRAWAL, TRANSFER, SPOT_TRADE, ACCOUNT_UPDATE, AMM_UPDATE, SIGNATURE_VERIFICATION, NFT_MINT, // L2 NFT mint or L1-to-L2 NFT deposit NFT_DATA } enum NftType { ERC1155, ERC721 } // -- Structs -- struct Token { address token; } struct ProtocolFeeData { uint32 syncedAt; // only valid before 2105 (85 years to go) uint8 takerFeeBips; uint8 makerFeeBips; uint8 previousTakerFeeBips; uint8 previousMakerFeeBips; } // General auxiliary data for each conditional transaction struct AuxiliaryData { uint txIndex; bool approved; bytes data; } // This is the (virtual) block the owner needs to submit onchain to maintain the // per-exchange (virtual) blockchain. struct Block { uint8 blockType; uint16 blockSize; uint8 blockVersion; bytes data; uint256[8] proof; // Whether we should store the @BlockInfo for this block on-chain. bool storeBlockInfoOnchain; // Block specific data that is only used to help process the block on-chain. // It is not used as input for the circuits and it is not necessary for data-availability. // This bytes array contains the abi encoded AuxiliaryData[] data. bytes auxiliaryData; // Arbitrary data, mainly for off-chain data-availability, i.e., // the multihash of the IPFS file that contains the block data. bytes offchainData; } struct BlockInfo { // The time the block was submitted on-chain. uint32 timestamp; // The public data hash of the block (the 28 most significant bytes). bytes28 blockDataHash; } // Represents an onchain deposit request. struct Deposit { uint96 amount; uint64 timestamp; } // A forced withdrawal request. // If the actual owner of the account initiated the request (we don't know who the owner is // at the time the request is being made) the full balance will be withdrawn. struct ForcedWithdrawal { address owner; uint64 timestamp; } struct Constants { uint SNARK_SCALAR_FIELD; uint MAX_OPEN_FORCED_REQUESTS; uint MAX_AGE_FORCED_REQUEST_UNTIL_WITHDRAW_MODE; uint TIMESTAMP_HALF_WINDOW_SIZE_IN_SECONDS; uint MAX_NUM_ACCOUNTS; uint MAX_NUM_TOKENS; uint MIN_AGE_PROTOCOL_FEES_UNTIL_UPDATED; uint MIN_TIME_IN_SHUTDOWN; uint TX_DATA_AVAILABILITY_SIZE; uint MAX_AGE_DEPOSIT_UNTIL_WITHDRAWABLE_UPPERBOUND; } // This is the prime number that is used for the alt_bn128 elliptic curve, see EIP-196. uint public constant SNARK_SCALAR_FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617; uint public constant MAX_OPEN_FORCED_REQUESTS = 4096; uint public constant MAX_AGE_FORCED_REQUEST_UNTIL_WITHDRAW_MODE = 15 days; uint public constant TIMESTAMP_HALF_WINDOW_SIZE_IN_SECONDS = 7 days; uint public constant MAX_NUM_ACCOUNTS = 2 ** 32; uint public constant MAX_NUM_TOKENS = 2 ** 16; uint public constant MIN_AGE_PROTOCOL_FEES_UNTIL_UPDATED = 7 days; uint public constant MIN_TIME_IN_SHUTDOWN = 30 days; // The amount of bytes each rollup transaction uses in the block data for data-availability. // This is the maximum amount of bytes of all different transaction types. uint32 public constant MAX_AGE_DEPOSIT_UNTIL_WITHDRAWABLE_UPPERBOUND = 15 days; uint32 public constant ACCOUNTID_PROTOCOLFEE = 0; uint public constant TX_DATA_AVAILABILITY_SIZE = 68; uint public constant TX_DATA_AVAILABILITY_SIZE_PART_1 = 29; uint public constant TX_DATA_AVAILABILITY_SIZE_PART_2 = 39; uint public constant NFT_TOKEN_ID_START = 2 ** 15; struct AccountLeaf { uint32 accountID; address owner; uint pubKeyX; uint pubKeyY; uint32 nonce; uint feeBipsAMM; } struct BalanceLeaf { uint16 tokenID; uint96 balance; uint weightAMM; uint storageRoot; } struct Nft { address minter; // Minter address for a L2 mint or // the NFT's contract address in the case of a L1-to-L2 NFT deposit. NftType nftType; address token; uint256 nftID; uint8 creatorFeeBips; } struct MerkleProof { ExchangeData.AccountLeaf accountLeaf; ExchangeData.BalanceLeaf balanceLeaf; ExchangeData.Nft nft; uint[48] accountMerkleProof; uint[24] balanceMerkleProof; } struct BlockContext { bytes32 DOMAIN_SEPARATOR; uint32 timestamp; Block block; uint txIndex; } // Represents the entire exchange state except the owner of the exchange. struct State { uint32 maxAgeDepositUntilWithdrawable; bytes32 DOMAIN_SEPARATOR; ILoopringV3 loopring; IBlockVerifier blockVerifier; IAgentRegistry agentRegistry; IDepositContract depositContract; // The merkle root of the offchain data stored in a Merkle tree. The Merkle tree // stores balances for users using an account model. bytes32 merkleRoot; // List of all blocks mapping(uint => BlockInfo) blocks; uint numBlocks; // List of all tokens Token[] tokens; // A map from a token to its tokenID + 1 mapping (address => uint16) tokenToTokenId; // A map from an accountID to a tokenID to if the balance is withdrawn mapping (uint32 => mapping (uint16 => bool)) withdrawnInWithdrawMode; // A map from an account to a token to the amount withdrawable for that account. // This is only used when the automatic distribution of the withdrawal failed. mapping (address => mapping (uint16 => uint)) amountWithdrawable; // A map from an account to a token to the forced withdrawal (always full balance) // The `uint16' represents ERC20 token ID (if < NFT_TOKEN_ID_START) or // NFT balance slot (if >= NFT_TOKEN_ID_START) mapping (uint32 => mapping (uint16 => ForcedWithdrawal)) pendingForcedWithdrawals; // A map from an address to a token to a deposit mapping (address => mapping (uint16 => Deposit)) pendingDeposits; // A map from an account owner to an approved transaction hash to if the transaction is approved or not mapping (address => mapping (bytes32 => bool)) approvedTx; // A map from an account owner to a destination address to a tokenID to an amount to a storageID to a new recipient address mapping (address => mapping (address => mapping (uint16 => mapping (uint => mapping (uint32 => address))))) withdrawalRecipient; // Counter to keep track of how many of forced requests are open so we can limit the work that needs to be done by the owner uint32 numPendingForcedTransactions; // Cached data for the protocol fee ProtocolFeeData protocolFeeData; // Time when the exchange was shutdown uint shutdownModeStartTime; // Time when the exchange has entered withdrawal mode uint withdrawalModeStartTime; // Last time the protocol fee was withdrawn for a specific token mapping (address => uint) protocolFeeLastWithdrawnTime; // Duplicated loopring address address loopringAddr; // AMM fee bips uint8 ammFeeBips; // Enable/Disable `onchainTransferFrom` bool allowOnchainTransferFrom; // owner => NFT type => token address => nftID => Deposit mapping (address => mapping (NftType => mapping (address => mapping(uint256 => Deposit)))) pendingNFTDeposits; // owner => minter => NFT type => token address => nftID => amount withdrawable // This is only used when the automatic distribution of the withdrawal failed. mapping (address => mapping (address => mapping (NftType => mapping (address => mapping(uint256 => uint))))) amountWithdrawableNFT; } } // File: contracts/core/impl/libexchange/ExchangeMode.sol // Copyright 2017 Loopring Technology Limited. /// @title ExchangeMode. /// @dev All methods in this lib are internal, therefore, there is no need /// to deploy this library independently. /// @author Brecht Devos - <[email protected]> /// @author Daniel Wang - <[email protected]> library ExchangeMode { using MathUint for uint; function isInWithdrawalMode( ExchangeData.State storage S ) internal // inline call view returns (bool result) { result = S.withdrawalModeStartTime > 0; } function isShutdown( ExchangeData.State storage S ) internal // inline call view returns (bool) { return S.shutdownModeStartTime > 0; } function getNumAvailableForcedSlots( ExchangeData.State storage S ) internal view returns (uint) { return ExchangeData.MAX_OPEN_FORCED_REQUESTS - S.numPendingForcedTransactions; } } // File: contracts/core/impl/libexchange/ExchangeTokens.sol // Copyright 2017 Loopring Technology Limited. /// @title ExchangeTokens. /// @author Daniel Wang - <[email protected]> /// @author Brecht Devos - <[email protected]> library ExchangeTokens { using MathUint for uint; using ERC20SafeTransfer for address; using ExchangeMode for ExchangeData.State; event TokenRegistered( address token, uint16 tokenId ); function getTokenAddress( ExchangeData.State storage S, uint16 tokenID ) public view returns (address) { require(tokenID < S.tokens.length, "INVALID_TOKEN_ID"); return S.tokens[tokenID].token; } function registerToken( ExchangeData.State storage S, address tokenAddress ) public returns (uint16 tokenID) { require(!S.isInWithdrawalMode(), "INVALID_MODE"); require(S.tokenToTokenId[tokenAddress] == 0, "TOKEN_ALREADY_EXIST"); require(S.tokens.length < ExchangeData.NFT_TOKEN_ID_START, "TOKEN_REGISTRY_FULL"); // Check if the deposit contract supports the new token if (S.depositContract != IDepositContract(0)) { require( S.depositContract.isTokenSupported(tokenAddress), "UNSUPPORTED_TOKEN" ); } // Assign a tokenID and store the token ExchangeData.Token memory token = ExchangeData.Token( tokenAddress ); tokenID = uint16(S.tokens.length); S.tokens.push(token); S.tokenToTokenId[tokenAddress] = tokenID + 1; emit TokenRegistered(tokenAddress, tokenID); } function getTokenID( ExchangeData.State storage S, address tokenAddress ) internal // inline call view returns (uint16 tokenID) { tokenID = S.tokenToTokenId[tokenAddress]; require(tokenID != 0, "TOKEN_NOT_FOUND"); tokenID = tokenID - 1; } function isNFT(uint16 tokenID) internal // inline call pure returns (bool) { return tokenID >= ExchangeData.NFT_TOKEN_ID_START; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"TokenRegistered","type":"event"}]
Contract Creation Code
610635610026600b82828239805160001a60731461001957fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c806336d626e914610045578063f24789a81461007b575b600080fd5b81801561005157600080fd5b50610065610060366004610421565b61009b565b60405161007291906105f0565b60405180910390f35b61008e610089366004610468565b610371565b6040516100729190610492565b60006100a6836103f1565b156100e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd90610514565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a8401602052604090205461ffff1615610149576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd906105b9565b600983015461800011610188576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd906104dd565b600583015473ffffffffffffffffffffffffffffffffffffffff16156102865760058301546040517f75151b6300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906375151b6390610200908590600401610492565b60206040518083038186803b15801561021857600080fd5b505afa15801561022c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025091906103fa565b610286576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd90610582565b50604080516020808201835273ffffffffffffffffffffffffffffffffffffffff848116808452600987018054600181018083556000928352858320875190830180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169190961617909455918152600a88019093529184902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661ffff90921691909117905591517f678eb1f52e3e76c52c1143d5699af1d8a5e03743e8840223ccb27aabf3c44c0a9061036290859085906104b3565b60405180910390a15092915050565b600982015460009061ffff8316106103b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd9061054b565b826009018261ffff16815481106103c857fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169392505050565b60140154151590565b60006020828403121561040b578081fd5b8151801515811461041a578182fd5b9392505050565b60008060408385031215610433578081fd5b82359150602083013573ffffffffffffffffffffffffffffffffffffffff8116811461045d578182fd5b809150509250929050565b6000806040838503121561047a578182fd5b82359150602083013561ffff8116811461045d578182fd5b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92909216825261ffff16602082015260400190565b60208082526013908201527f544f4b454e5f52454749535452595f46554c4c00000000000000000000000000604082015260600190565b6020808252600c908201527f494e56414c49445f4d4f44450000000000000000000000000000000000000000604082015260600190565b60208082526010908201527f494e56414c49445f544f4b454e5f494400000000000000000000000000000000604082015260600190565b60208082526011908201527f554e535550504f525445445f544f4b454e000000000000000000000000000000604082015260600190565b60208082526013908201527f544f4b454e5f414c52454144595f455849535400000000000000000000000000604082015260600190565b61ffff9190911681526020019056fea26469706673582212204258e90d544c4a82572cfdc2afadc09cf9f3526d8dd9da9d5ec81fe412c7d51064736f6c63430007060033
Deployed Bytecode
0x7324f51fadc255dfcbc436615167c325cac7010b2930146080604052600436106100405760003560e01c806336d626e914610045578063f24789a81461007b575b600080fd5b81801561005157600080fd5b50610065610060366004610421565b61009b565b60405161007291906105f0565b60405180910390f35b61008e610089366004610468565b610371565b6040516100729190610492565b60006100a6836103f1565b156100e6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd90610514565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166000908152600a8401602052604090205461ffff1615610149576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd906105b9565b600983015461800011610188576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd906104dd565b600583015473ffffffffffffffffffffffffffffffffffffffff16156102865760058301546040517f75151b6300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff909116906375151b6390610200908590600401610492565b60206040518083038186803b15801561021857600080fd5b505afa15801561022c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061025091906103fa565b610286576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd90610582565b50604080516020808201835273ffffffffffffffffffffffffffffffffffffffff848116808452600987018054600181018083556000928352858320875190830180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169190961617909455918152600a88019093529184902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001661ffff90921691909117905591517f678eb1f52e3e76c52c1143d5699af1d8a5e03743e8840223ccb27aabf3c44c0a9061036290859085906104b3565b60405180910390a15092915050565b600982015460009061ffff8316106103b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100dd9061054b565b826009018261ffff16815481106103c857fe5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff169392505050565b60140154151590565b60006020828403121561040b578081fd5b8151801515811461041a578182fd5b9392505050565b60008060408385031215610433578081fd5b82359150602083013573ffffffffffffffffffffffffffffffffffffffff8116811461045d578182fd5b809150509250929050565b6000806040838503121561047a578182fd5b82359150602083013561ffff8116811461045d578182fd5b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b73ffffffffffffffffffffffffffffffffffffffff92909216825261ffff16602082015260400190565b60208082526013908201527f544f4b454e5f52454749535452595f46554c4c00000000000000000000000000604082015260600190565b6020808252600c908201527f494e56414c49445f4d4f44450000000000000000000000000000000000000000604082015260600190565b60208082526010908201527f494e56414c49445f544f4b454e5f494400000000000000000000000000000000604082015260600190565b60208082526011908201527f554e535550504f525445445f544f4b454e000000000000000000000000000000604082015260600190565b60208082526013908201527f544f4b454e5f414c52454144595f455849535400000000000000000000000000604082015260600190565b61ffff9190911681526020019056fea26469706673582212204258e90d544c4a82572cfdc2afadc09cf9f3526d8dd9da9d5ec81fe412c7d51064736f6c63430007060033
Deployed Bytecode Sourcemap
33984:2074:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34522:1011;;;;;;;;;;-1:-1:-1;34522:1011:0;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;34238:276;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;34522:1011::-;34660:14;34701:22;:1;:20;:22::i;:::-;34700:23;34692:48;;;;;;;;;;;;:::i;:::-;;;;;;;;;34759:30;;;;;;;:16;;;:30;;;;;;;;:35;34751:67;;;;;;;;;;;;:::i;:::-;34837:8;;;:15;28024:7;-1:-1:-1;34829:81:0;;;;;;;;;;;;:::i;:::-;34992:17;;;;:40;:17;:40;34988:200;;35075:17;;;;:48;;;;;:17;;;;;:34;;:48;;35110:12;;35075:48;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;35049:127;;;;;;;;;;;;:::i;:::-;-1:-1:-1;35283:56:0;;;;;;;;;;;;;;;;35367:8;;;:15;;35394:20;;;;;;-1:-1:-1;35394:20:0;;;;;;;;;;;;;;;;;;;;;;;35425:30;;;:16;;;:30;;;;;;;:44;;;;;;;;;;;;;;35487:38;;;;;;35283:56;;35367:15;;35487:38;:::i;:::-;;;;;;;;34522:1011;;;;;:::o;34238:276::-;34429:8;;;:15;34386:7;;34419:25;;;;34411:54;;;;;;;;;;;;:::i;:::-;34483:1;:8;;34492:7;34483:17;;;;;;;;;;;;;;;;;;;:23;;;;34238:276;-1:-1:-1;;;34238:276:0:o;33050:218::-;33231:25;;;:29;;;33050:218::o;14:297:1:-;;134:2;122:9;113:7;109:23;105:32;102:2;;;155:6;147;140:22;102:2;192:9;186:16;245:5;238:13;231:21;224:5;221:32;211:2;;272:6;264;257:22;211:2;300:5;92:219;-1:-1:-1;;;92:219:1:o;316:421::-;;;469:2;457:9;448:7;444:23;440:32;437:2;;;490:6;482;475:22;437:2;531:9;518:23;508:33;;591:2;580:9;576:18;563:32;635:42;628:5;624:54;617:5;614:65;604:2;;698:6;690;683:22;604:2;726:5;716:15;;;427:310;;;;;:::o;742:384::-;;;894:2;882:9;873:7;869:23;865:32;862:2;;;915:6;907;900:22;862:2;956:9;943:23;933:33;;1016:2;1005:9;1001:18;988:32;1060:6;1053:5;1049:18;1042:5;1039:29;1029:2;;1087:6;1079;1072:22;1131:234;1315:42;1303:55;;;;1285:74;;1273:2;1258:18;;1240:125::o;1601:308::-;1803:42;1791:55;;;;1773:74;;1895:6;1883:19;1878:2;1863:18;;1856:47;1761:2;1746:18;;1728:181::o;1914:343::-;2116:2;2098:21;;;2155:2;2135:18;;;2128:30;2194:21;2189:2;2174:18;;2167:49;2248:2;2233:18;;2088:169::o;2262:336::-;2464:2;2446:21;;;2503:2;2483:18;;;2476:30;2542:14;2537:2;2522:18;;2515:42;2589:2;2574:18;;2436:162::o;2603:340::-;2805:2;2787:21;;;2844:2;2824:18;;;2817:30;2883:18;2878:2;2863:18;;2856:46;2934:2;2919:18;;2777:166::o;2948:341::-;3150:2;3132:21;;;3189:2;3169:18;;;3162:30;3228:19;3223:2;3208:18;;3201:47;3280:2;3265:18;;3122:167::o;3294:343::-;3496:2;3478:21;;;3535:2;3515:18;;;3508:30;3574:21;3569:2;3554:18;;3547:49;3628:2;3613:18;;3468:169::o;3642:196::-;3824:6;3812:19;;;;3794:38;;3782:2;3767:18;;3749:89::o
Swarm Source
ipfs://4258e90d544c4a82572cfdc2afadc09cf9f3526d8dd9da9d5ec81fe412c7d510
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.