├── .gitattributes ├── .gitignore ├── .gitmodules ├── Circuit Design.md ├── DeGate Protocol Specification Document.md ├── README.md ├── Smart Contract Design.md ├── images ├── asset_merkle_tree.png ├── entire_merkle_tree.png └── logic_circuit.png ├── lerna.json ├── package-lock.json ├── package.json └── packages ├── loopring_v3.js ├── README.md ├── globals.d.ts ├── index.ts ├── package-lock.json ├── package.json ├── src │ ├── babyjub.js │ ├── bitstream.ts │ ├── bitstreamEx.ts │ ├── compression.ts │ ├── constants.ts │ ├── eddsa.ts │ ├── exchange_v3.ts │ ├── explorer.ts │ ├── float.ts │ ├── logs.ts │ ├── main.ts │ ├── poseidon.js │ ├── protocol_v3.ts │ ├── request_processors │ │ ├── account_update_processor.ts │ │ ├── appkey_update_processor.ts │ │ ├── batch_spot_trade_processor.ts │ │ ├── deposit_processor.ts │ │ ├── order_cancel_processor.ts │ │ ├── spot_trade_processor.ts │ │ ├── transfer_processor.ts │ │ └── withdrawal_processor.ts │ ├── sparse_merkle_tree.ts │ └── types.ts └── tsconfig.json └── loopring_v3 ├── .eslintrc.js ├── .gitignore ├── .prettierrc ├── .solcover.js ├── .soliumignore ├── .soliumrc.json ├── .travis.yml ├── CMakeLists.txt ├── LICENSE ├── Makefile ├── README.md ├── circuit ├── .clang-format ├── CMakeLists.txt ├── Circuits │ ├── AccountUpdateCircuit.h │ ├── AppKeyUpdateCircuit.h │ ├── BaseTransactionCircuit.h │ ├── BatchSpotTradeCircuit.h │ ├── Circuit.h │ ├── DepositCircuit.h │ ├── NoopCircuit.h │ ├── OrderCancelCircuit.h │ ├── SpotTradeCircuit.h │ ├── TransferCircuit.h │ ├── UniversalCircuit.h │ └── WithdrawCircuit.h ├── Gadgets │ ├── AccountGadgets.h │ ├── BatchOrderGadgets.h │ ├── MatchingGadgets.h │ ├── MathGadgets.h │ ├── MerkleTree.h │ ├── OrderGadgets.h │ ├── SignatureGadgets.h │ └── StorageGadgets.h ├── ThirdParty │ ├── BigInt.hpp │ ├── BigIntHeader.hpp │ ├── catch.hpp │ ├── httplib.h │ └── json.hpp ├── Utils │ ├── Constants.h │ ├── Data.h │ └── Utils.h ├── buildCircuit.sh ├── cuda_prover │ ├── cuda_prover.cu │ └── multiexp │ │ ├── arith.cu │ │ ├── curves.cu │ │ ├── fixnum.cu │ │ ├── primitives.cu │ │ └── reduce.cu ├── docker │ ├── Dockerfile │ ├── entrypoint-host.sh │ └── entrypoint.sh ├── main.cpp ├── pom.xml ├── statements.md └── test │ ├── AccuntUpdateTests.cpp │ ├── FloatTests.cpp │ ├── MatchingTests.cpp │ ├── MathTests.cpp │ ├── MerkleTreeTests.cpp │ ├── OrderTests.cpp │ ├── SignatureTests.cpp │ ├── StorageTests.cpp │ ├── TestUtils.h │ ├── data │ ├── block.json │ ├── config.json │ └── protoBlock.json │ └── main.cpp ├── contracts-solpp ├── BlockVerifier.solpp ├── ExchangeData.solpp ├── ExchangeV3.solpp ├── IBlockVerifier.solpp └── IExchangeV3.solpp ├── contracts ├── Migrations.sol ├── aux │ ├── access │ │ ├── DelayedOwner.sol │ │ ├── DelayedTransaction.sol │ │ ├── IBlockReceiver.sol │ │ ├── IDelayedTransaction.sol │ │ ├── LoopringIOExchangeOwner.sol │ │ └── SelectorBasedAccessManager.sol │ ├── agents │ │ ├── AgentRegistry.sol │ │ ├── FastWithdrawalAgent.sol │ │ └── ForcedWithdrawalAgent.sol │ ├── compression │ │ ├── LzDecompressor.sol │ │ └── ZeroDecompressor.sol │ ├── fast-withdrawal │ │ └── FastWithdrawalLiquidityProvider.sol │ ├── fee-vault │ │ ├── IProtocolFeeVault.sol │ │ └── ProtocolFeeVault.sol │ ├── migrate │ │ └── MigrationToLoopringExchangeV2.sol │ └── token-sellers │ │ └── ITokenSeller.sol ├── core │ ├── iface │ │ ├── ExchangeData.sol │ │ ├── IAgentRegistry.sol │ │ ├── IBlockVerifier.sol │ │ ├── IDepositContract.sol │ │ ├── IExchangeV3.sol │ │ └── ILoopringV3.sol │ └── impl │ │ ├── BlockVerifier.sol │ │ ├── DefaultDepositContract.sol │ │ ├── ExchangeV3.sol │ │ ├── LoopringV3.sol │ │ ├── VerificationKeys.sol │ │ ├── libexchange │ │ ├── ExchangeAdmins.sol │ │ ├── ExchangeBalances.sol │ │ ├── ExchangeBlocks.sol │ │ ├── ExchangeDeposits.sol │ │ ├── ExchangeGenesis.sol │ │ ├── ExchangeMode.sol │ │ ├── ExchangeSignatures.sol │ │ ├── ExchangeTokens.sol │ │ └── ExchangeWithdrawals.sol │ │ └── libtransactions │ │ ├── AccountUpdateTransaction.sol │ │ ├── BlockReader.sol │ │ ├── DepositTransaction.sol │ │ └── WithdrawTransaction.sol ├── lib │ ├── AddressSet.sol │ ├── AddressUtil.sol │ ├── BurnableERC20.sol │ ├── Claimable.sol │ ├── Create2.sol │ ├── Drainable.sol │ ├── EIP712.sol │ ├── ERC1271.sol │ ├── ERC20.sol │ ├── ERC20SafeTransfer.sol │ ├── ERC20Token.sol │ ├── ERC2612.sol │ ├── FloatUtil.sol │ ├── MathUint.sol │ ├── MathUint248.sol │ ├── MathUint96.sol │ ├── Ownable.sol │ ├── OwnerManagable.sol │ ├── Poseidon.sol │ ├── ReentrancyGuard.sol │ ├── SignatureUtil.sol │ └── SimpleProxy.sol ├── test │ ├── DelayedOwnerContract.sol │ ├── DelayedTargetContract.sol │ ├── DummyToken.sol │ ├── LPERC20.sol │ ├── LRCToken.sol │ ├── LzDecompressorContract.sol │ ├── PoseidonContract.sol │ ├── TestAccountContract.sol │ ├── TransferContract.sol │ ├── ZeroDecompressorContract.sol │ └── tokens │ │ ├── GTO.sol │ │ ├── INDA.sol │ │ ├── INDB.sol │ │ ├── LRC.sol │ │ ├── RDN.sol │ │ ├── REP.sol │ │ ├── TEST.sol │ │ └── WETH.sol └── thirdparty │ ├── BytesUtil.sol │ ├── Cloneable.sol │ ├── MockContract.sol │ ├── SafeCast.sol │ ├── chainlink │ └── AggregatorInterface.sol │ ├── chi │ └── IChiToken.sol │ ├── opengsn2 │ ├── BaseRelayRecipient.sol │ ├── IKnowForwarderAddress.sol │ └── IRelayRecipient.sol │ ├── proxies │ ├── OwnedUpgradabilityProxy.sol │ ├── Proxy.sol │ └── UpgradabilityProxy.sol │ ├── timelock │ ├── SafeMath.sol │ └── Timelock.sol │ └── verifiers │ ├── BatchVerifier.sol │ └── Verifier.sol ├── deploy-contract-install.sh ├── deployment └── flatten-all.sh ├── docker ├── .gitignore ├── Dockerfile ├── build_image.sh └── docker_ganache.sh ├── ganache.sh ├── genAbi.js ├── genAbi.sh ├── globals.d.ts ├── install ├── migrations-scripts ├── 21_grantAccessSubmitblock.js ├── 22_registerCircuit.js ├── 23_reDeploy_BlockVerifier.js ├── 24_registerToken.js ├── 27_setDepositParams.js ├── 28_getExchangeData.js ├── 29_updateForceWithdrawFee.js └── 30_updateProtocolFeeSettings_delay.js ├── migrations ├── 1_initial_migration.js ├── 2_deploy_thirdparty.js ├── 3_deploy_tokens.js ├── 4_deploy_auxiliaries.js ├── 5_deploy_protocol_v3.js ├── 6_deploy_exchange_v3_libs.js ├── 8_deploy_exchange_v3.js └── 9_summary.js ├── operator ├── calculate.py ├── create_block.py ├── float.py ├── generate_keys.py ├── sparse_merkle_tree.py └── state.py ├── package-lock.json ├── package.json ├── security_audit ├── DeGate_Report_EN-final2023.pdf ├── DeGate_Report_EN-final20230912.pdf ├── Least Authority - DeGate DAO DeGate Smart Contracts Updated Final Audit Report.pdf ├── Least Authority - DeGate Technology DeGate zk-SNARK Circuit Final Audit Report.pdf ├── Least Authority - Loopring 3.6 Design + Implementation - Circuit Final Audit Report.pdf ├── Least Authority - Loopring 3.6 Design + Implementation - Smart Contracts Final Audit Report.pdf ├── LoopringV3_1_Report_CN.pdf ├── LoopringV3_1_Report_EN.pdf ├── LoopringV3_6_vs_V3_1.pdf └── Trailofbits - DeGate Final Audit Report.pdf ├── sol-preprocess.sh ├── test ├── all_16_vk.json ├── bitarray.ts ├── context.ts ├── expectThrow.ts ├── logs.ts ├── simulator.ts ├── testAppKeyUpdate.ts ├── testAutoMarket.ts ├── testBatchSpotTrade.ts ├── testBatchSpotTradeOther.ts ├── testBlockVerifier.ts ├── testClaimable.ts ├── testCompression.ts ├── testDebugTools.ts ├── testDefaultDepositContract.ts ├── testDelayedOwner.ts ├── testExchangeAccounts.ts ├── testExchangeAdmin.ts ├── testExchangeBlockPermutations.ts ├── testExchangeBlocks.ts ├── testExchangeContext.ts ├── testExchangeDepositByTransfer.ts ├── testExchangeDepositWithdraw.ts ├── testExchangeNonReentrant.ts ├── testExchangeRingSettlement.ts ├── testExchangeShutdown.ts ├── testExchangeTokens.ts ├── testExchangeTransfer.ts ├── testExchangeUtil.ts ├── testExchangeWithdraw.ts ├── testExchangeWithdrawalMode.ts ├── testLoopring.ts ├── testOperator.ts ├── testOrderCancel.ts ├── testOwnable.ts ├── testPoseidon.ts ├── testProtocolFeeBipsUpdate.ts ├── testProtocolFeeVault.ts ├── testSpotTrade.ts ├── testStorageID.ts ├── testTransfers.ts └── types.ts ├── truffle.js ├── trusted_setup_keys ├── all_100_vk.json ├── all_10_vk.json ├── all_150_vk.json ├── all_200_vk.json ├── all_250_vk.json ├── all_25_vk.json ├── all_300_vk.json ├── all_355_vk.json ├── all_50_vk.json └── all_5_vk.json ├── tsconfig.json ├── util ├── Artifacts.ts ├── Signature.ts ├── TimeTravel.ts ├── find_optimal_poseidon.py ├── generate_keys_contract.py └── generate_poseidon_EVM_code.py └── verify_all_contracts.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | *.sol linguist-language=Solidity 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | transpiled/ 4 | .DS_Store 5 | .node-* 6 | *.log 7 | ganache_account_keys.txt 8 | deployedAddresses.json 9 | yarn.lock 10 | .idea/ 11 | dist/ 12 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "packages/loopring_v3/ethsnarks"] 2 | path = packages/loopring_v3/ethsnarks 3 | url = https://github.com/degatedev/ethsnarks 4 | branch = opt 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeGate Protocol using zkSNARKs 2 | 3 | ## About 4 | 5 | DeGate is a Decentralized Exchange (DEX) protocol built on Zero Knowledge (ZK) technology. As a ZK Rollup, DeGate fills a key gap in the market by providing spot order book trading and grid trading within the Ethereum ecosystem, offering an experience similar to centralized exchanges (CEX). 6 | To understand several concepts introduced by the DeGate Protocol, please read our [documentation](https://docs.degate.com/what-is-degate/) for DeGate protocol. 7 | 8 | ## Top Features 9 | 10 | - Onchain data-availability (DEXes can opt out for even greater throughput & lower cost) 11 | - ERC20 tokens and Ether are supported by default 12 | - Onchain deposit + on-chain & offchain withdrawal support 13 | - Support onchain and offchain order cancellation and order time-to-live settings 14 | - Allow partial order matching (aka partial fill) and offchain order-scaling 15 | - Multiple circuit permutations for different request batch sizes 16 | - Use tokens/ether traded as trading fee 17 | - A built-in mechanism to force DEX operators to fulfill duties in time 18 | - Support a unique feature called Order Aliasing 19 | - 100% secure for end users, even when DEX operators are evil 20 | - Grid trading capabilities with automatic/customizable strategies through parameters control 21 | - Batch spot trading significantly boosts protocol TPS and reduces transactional cost & fees 22 | - Gas fees reduction for deposits via the transfer deposit feature 23 | - and more... 24 | 25 | ## Etherscan.io Code Verification 26 | 27 | You can run `truffle-flattener ` to flatten a file. For contracts with constructor arguments, use https://abi.hashex.org/ to generated the argument string. To verify on etherscan.io, you also need to learn which libraries are linked to each contract from the migration scripts. 28 | -------------------------------------------------------------------------------- /images/asset_merkle_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/images/asset_merkle_tree.png -------------------------------------------------------------------------------- /images/entire_merkle_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/images/entire_merkle_tree.png -------------------------------------------------------------------------------- /images/logic_circuit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/images/logic_circuit.png -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "independent", 3 | "npmClient": "yarn", 4 | "useWorkspaces": true 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "degate_protocols", 3 | "version": "0.1.0", 4 | "description": "degate monorepo", 5 | "main": "index.js", 6 | "repository": "https://github.com/degatedev/protocols.git", 7 | "author": "DeGate Fundation", 8 | "license": "MIT", 9 | "private": true, 10 | "workspaces": [ 11 | "packages/*" 12 | ], 13 | "scripts": { 14 | "lerna": "lerna", 15 | "wsrun": "wsrun", 16 | "build": "lerna link && wsrun build $PKG --fast-exit -r --stages --exclude-missing" 17 | }, 18 | "devDependencies": { 19 | "lerna": "^3.16.0", 20 | "wsrun": "^5.0.2", 21 | "husky": "^4.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/README.md: -------------------------------------------------------------------------------- 1 | ## run Main with debug info: 2 | ~~~ 3 | npm start -- -x 4 | ~~~ 5 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module "bn.js"; 2 | declare module "ethereumjs-abi"; 3 | declare module "ethereumjs-util"; 4 | declare module "es6-promisify"; 5 | declare module "sha2"; 6 | declare module "snarkjs"; 7 | 8 | declare var assert: any; 9 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/index.ts: -------------------------------------------------------------------------------- 1 | const poseidon = require("./src/poseidon"); 2 | export class Poseidon { 3 | public static createHash(t: number, nRoundsF: number, nRoundsP: number) { 4 | return poseidon.createHash(t, nRoundsF, nRoundsP); 5 | } 6 | } 7 | 8 | export * from "./src/types"; 9 | export * from "./src/bitstream"; 10 | export * from "./src/bitstreamEx"; 11 | export * from "./src/compression"; 12 | export * from "./src/constants"; 13 | export * from "./src/eddsa"; 14 | export * from "./src/float"; 15 | export * from "./src/protocol_v3"; 16 | export * from "./src/exchange_v3"; 17 | export * from "./src/explorer"; 18 | export * from "./src/request_processors/spot_trade_processor"; 19 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "degate.js", 3 | "version": "0.1.0", 4 | "description": "degate.js", 5 | "main": "build/index.js", 6 | "types": "build/index.d.ts", 7 | "files": [ 8 | "build/**/*" 9 | ], 10 | "scripts": { 11 | "start": "tsc -p .; node build/src/main.js", 12 | "test": "echo \"Error: no test specified\" && exit 1", 13 | "compile": "tsc -p ." 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "devDependencies": { 18 | "@types/bignumber.js": "^5.0.0", 19 | "@types/bluebird": "3.5.33", 20 | "@types/lodash": "^4.14.136", 21 | "@types/node": "14.14.12", 22 | "@types/request-promise-native": "^1.0.15", 23 | "@typescript-eslint/eslint-plugin": "^4.33.0", 24 | "@typescript-eslint/parser": "^4.33.0", 25 | "ajv": "^6.10.0", 26 | "chai": "^4.2.0", 27 | "copyfiles": "^2.1.0", 28 | "diff": ">=3.5.0", 29 | "dirty-chai": "^2.0.1", 30 | "eslint": "^7.0.0", 31 | "eslint-config-google": "^0.14.0", 32 | "eslint-config-prettier": "^6.0.0", 33 | "eslint-plugin-prettier": "^3.1.0", 34 | "ethlint": "^1.2.4", 35 | "husky": "^4.0.4", 36 | "mocha": "^8.2.1", 37 | "node": "^13.10.1", 38 | "node-gyp": "^7.1.1", 39 | "npm": "^6.13.2", 40 | "npm-watch": "^0.6.0", 41 | "prettier": "^1.18.2", 42 | "pretty-quick": "^2.0.0", 43 | "types-bn": "0.0.1", 44 | "typescript": "4.0.5", 45 | "webpack": "^5.1.2" 46 | }, 47 | "dependencies": { 48 | "@types/bitwise-xor": "0.0.31", 49 | "@types/web3": "^1.0.19", 50 | "any-promise": "1.3.0", 51 | "bignumber.js": "^4.1.0", 52 | "blake-hash": "^2.0.0", 53 | "blake2b": "^2.1.3", 54 | "bluebird": "^3.5.1", 55 | "bn.js": "^5.0.0", 56 | "braces": "^3.0.2", 57 | "chalk": "^3.0.0", 58 | "dotenv": "^8.0.0", 59 | "es6-iterator": "^2.0.3", 60 | "es6-map": "^0.1.5", 61 | "es6-promisify": "^6.0.2", 62 | "escape-string-regexp": "^2.0.0", 63 | "estraverse": "^4.2.0", 64 | "esutils": "^2.0.2", 65 | "ethereumjs-abi": "^0.6.5", 66 | "ethereumjs-util": "^6.1.0", 67 | "event-emitter": "^0.3.5", 68 | "events": "^3.0.0", 69 | "find-config": "^1.0.0", 70 | "js-sha3": "^0.8.0", 71 | "lodash": "^4.17.14", 72 | "node-bin-setup": "^1.0.6", 73 | "serialize-javascript": "^3.0.0", 74 | "sha2": "^1.0.2", 75 | "sha3": "^2.0.0", 76 | "snarkjs": "0.1.31", 77 | "typedarray-to-buffer": "^3.1.5", 78 | "web3": "^1.2.0" 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/bitstreamEx.ts: -------------------------------------------------------------------------------- 1 | import { BigNumber } from "bignumber.js"; 2 | import BN from "bn.js"; 3 | const abi = require("ethereumjs-abi"); 4 | 5 | export class BitstreamEx { 6 | private data: string; 7 | 8 | constructor() { 9 | this.data = "" 10 | } 11 | 12 | public addNumberForBits(x: number, numBits = 1) { 13 | var xBig = new BigNumber(x) 14 | const formattedData = this.padString(xBig.toString(2), numBits); 15 | return this.insert(formattedData); 16 | } 17 | 18 | public toHex(numBytes = 80) { 19 | var dataNum = new BigNumber(this.data, 2) 20 | return this.padString(dataNum.toString(16), numBytes * 2) 21 | } 22 | 23 | public print() { 24 | console.log("data:" + this.data) 25 | } 26 | 27 | private insert(x: string) { 28 | const offset = this.length(); 29 | this.data += x; 30 | return offset; 31 | } 32 | 33 | // Returns the number of bytes of data 34 | public length() { 35 | return this.data.length; 36 | } 37 | 38 | private padString(x: string, targetLength: number) { 39 | if (x.length > targetLength) { 40 | throw Error( 41 | "0x" + 42 | x + 43 | " is too big to fit in the requested length (" + 44 | targetLength + 45 | ")" 46 | ); 47 | } 48 | while (x.length < targetLength) { 49 | x = "0" + x; 50 | } 51 | return x; 52 | } 53 | } -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/constants.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { FloatEncoding } from "./float"; 3 | import { Balance } from "./types"; 4 | 5 | export class Constants { 6 | static readonly BINARY_TREE_DEPTH_STORAGE = 14; 7 | static readonly BINARY_TREE_DEPTH_ACCOUNTS = 32; 8 | static readonly BINARY_TREE_DEPTH_TOKENS = 32; 9 | 10 | static readonly TX_DATA_AVAILABILITY_SIZE = 83; 11 | 12 | static readonly TX_DATA_AVAILABILITY_SIZE_PART_1 = 80; 13 | static readonly TX_DATA_AVAILABILITY_SIZE_PART_2 = 3; 14 | 15 | static readonly NUM_BITS_ACCOUNTID = Constants.BINARY_TREE_DEPTH_ACCOUNTS; 16 | static readonly NUM_BITS_STORAGEID = 32; 17 | static readonly NUM_STORAGE_SLOTS = 2 ** Constants.BINARY_TREE_DEPTH_STORAGE; 18 | 19 | static readonly MAX_NUM_TOKENS = 4 ** 16; 20 | 21 | static readonly MAX_AMOUNT = new BN(2).pow(new BN(248)).sub(new BN(1)); 22 | 23 | static readonly FEE_MULTIPLIER = 50; 24 | 25 | static readonly Float32Encoding: FloatEncoding = { 26 | numBitsExponent: 7, 27 | numBitsMantissa: 25, 28 | exponentBase: 10 29 | }; 30 | 31 | static readonly Float29Encoding: FloatEncoding = { 32 | numBitsExponent: 5, 33 | numBitsMantissa: 24, 34 | exponentBase: 10 35 | }; 36 | 37 | static readonly Float24Encoding: FloatEncoding = { 38 | numBitsExponent: 5, 39 | numBitsMantissa: 19, 40 | exponentBase: 10 41 | }; 42 | 43 | static readonly Float23Encoding: FloatEncoding = { 44 | numBitsExponent: 5, 45 | numBitsMantissa: 18, 46 | exponentBase: 10 47 | }; 48 | 49 | static readonly Float16Encoding: FloatEncoding = { 50 | numBitsExponent: 5, 51 | numBitsMantissa: 11, 52 | exponentBase: 10 53 | }; 54 | 55 | static readonly emptyBytes: any = []; 56 | static readonly zeroAddress = "0x" + "00".repeat(20); 57 | 58 | static readonly scalarField = new BN( 59 | "21888242871839275222246405745257275088548364400416034343698204186575808495617", 60 | 10 61 | ); 62 | 63 | static readonly DefaultBalance: Balance = { 64 | balance: new BN(0) 65 | }; 66 | } 67 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/float.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | 3 | export interface FloatEncoding { 4 | numBitsExponent: number; 5 | numBitsMantissa: number; 6 | exponentBase: number; 7 | } 8 | 9 | export function toFloat(value: BN, encoding: FloatEncoding) { 10 | const maxExponent = (1 << encoding.numBitsExponent) - 1; 11 | const maxMantissa = (1 << encoding.numBitsMantissa) - 1; 12 | const maxExponentValue = new BN(encoding.exponentBase).pow( 13 | new BN(maxExponent) 14 | ); 15 | const maxValue = new BN(maxMantissa).mul(maxExponentValue); 16 | assert( 17 | value.lte(maxValue), 18 | "Value too large: " + 19 | value.toString(10) + 20 | ", max value: " + 21 | maxValue.toString(10) 22 | ); 23 | 24 | let exponent = 0; 25 | let r = value.div(new BN(maxMantissa)); 26 | let d = new BN(1); 27 | while ( 28 | r.gte(new BN(encoding.exponentBase)) || 29 | d.mul(new BN(maxMantissa)).lt(value) 30 | ) { 31 | r = r.div(new BN(encoding.exponentBase)); 32 | exponent += 1; 33 | d = d.mul(new BN(encoding.exponentBase)); 34 | } 35 | const mantissa = value.div(d).toNumber(); 36 | 37 | assert(exponent <= maxExponent, "Exponent too large"); 38 | assert(mantissa <= maxMantissa, "Mantissa too large"); 39 | const f = (exponent << encoding.numBitsMantissa) + mantissa; 40 | return f; 41 | } 42 | 43 | export function fromFloat(f: number, encoding: FloatEncoding) { 44 | const exponent = f >> encoding.numBitsMantissa; 45 | const mantissa = f & ((1 << encoding.numBitsMantissa) - 1); 46 | const value = new BN(mantissa).mul( 47 | new BN(encoding.exponentBase).pow(new BN(exponent)) 48 | ); 49 | return value; 50 | } 51 | 52 | export function roundToFloatValue(value: BN, encoding: FloatEncoding) { 53 | const f = toFloat(value, encoding); 54 | const floatValue = fromFloat(f, encoding); 55 | assert( 56 | floatValue.lte(value), 57 | "float value can never be higher than the original value" 58 | ); 59 | return floatValue; 60 | } 61 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/logs.ts: -------------------------------------------------------------------------------- 1 | import chalk from "chalk"; 2 | 3 | export function isInfoEnabled() { 4 | return process.argv.indexOf("-i") > -1 || isDebugEnabled(); 5 | } 6 | 7 | export function isDebugEnabled() { 8 | return process.argv.indexOf("-x") > -1; 9 | } 10 | 11 | export function INFO(...args: any[]) { 12 | if (isInfoEnabled()) { 13 | console.log(chalk.blue.bold(["[INFO]", ...args].join(" "))); 14 | } 15 | } 16 | 17 | export function DEBUG(...args: any[]) { 18 | if (isDebugEnabled()) { 19 | console.log(...args); 20 | } 21 | } 22 | 23 | export function WARN(...args: any[]) { 24 | console.log(chalk.magenta.bold(["[WARN]", ...args].join(" "))); 25 | } 26 | 27 | export function ERROR(...args: any[]) { 28 | console.log(chalk.red.bold.underline(["[ERROR]", ...args].join(" "))); 29 | } 30 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/main.ts: -------------------------------------------------------------------------------- 1 | import { Explorer } from "./explorer"; 2 | import Web3 from "web3"; 3 | const assert = require("assert"); 4 | eval("global.assert = assert;"); 5 | 6 | async function main() { 7 | const explorer = await new Explorer(); 8 | const ethNodeUrl = 9 | "https://mainnet.infura.io/v3/a06ed9c6b5424b61beafff27ecc3abf3"; 10 | const web3 = new Web3(new Web3.providers.HttpProvider(ethNodeUrl)); 11 | const universalRegistryAddress = "0x4c2103152a1A402af283fa52903569f05477611f"; 12 | const blockFrom = 8967526; 13 | explorer.initialize(web3, blockFrom); 14 | 15 | const blockTo = 9252045; 16 | const step = 200; 17 | 18 | await explorer.syncWithStep(blockTo, step); 19 | 20 | // for (let i = blockFrom; i <= blockTo; i += step ) { 21 | 22 | // } 23 | // explorer.sync(9252045); 24 | 25 | const exchange = explorer.getExchange(0); 26 | exchange.buildMerkleTreeForWithdrawalMode(); 27 | const withdrawData = exchange.getWithdrawFromMerkleTreeData(20, 2); 28 | console.log("withdrawData:", withdrawData); 29 | } 30 | 31 | main(); 32 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/request_processors/account_update_processor.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { Bitstream } from "../bitstream"; 3 | import { Constants } from "../constants"; 4 | import { EdDSA } from "../eddsa"; 5 | import { fromFloat } from "../float"; 6 | import { BlockContext, ExchangeState } from "../types"; 7 | 8 | interface AccountUpdate { 9 | owner?: string; 10 | accountID?: number; 11 | feeTokenID?: number; 12 | fee?: BN; 13 | publicKeyX?: string; 14 | publicKeyY?: string; 15 | validUntil?: number; 16 | nonce?: number; 17 | } 18 | 19 | /** 20 | * Processes account update requests. 21 | */ 22 | export class AccountUpdateProcessor { 23 | public static process( 24 | state: ExchangeState, 25 | block: BlockContext, 26 | txData: Bitstream 27 | ) { 28 | const update = AccountUpdateProcessor.extractData(txData); 29 | 30 | const accountID = state.ownerToAccountId[update.owner]; 31 | 32 | const account = state.getAccount(accountID); 33 | account.owner = update.owner; 34 | account.publicKeyX = update.publicKeyX; 35 | account.publicKeyY = update.publicKeyY; 36 | account.nonce++; 37 | 38 | const balance = account.getBalance(update.feeTokenID); 39 | balance.balance.isub(update.fee); 40 | 41 | const operator = state.getAccount(block.operatorAccountID); 42 | const balanceO = operator.getBalance(update.feeTokenID); 43 | balanceO.balance.iadd(update.fee); 44 | 45 | return update; 46 | } 47 | 48 | public static extractData(data: Bitstream) { 49 | const update: AccountUpdate = {}; 50 | let offset = 0; 51 | 52 | const updateType = data.extractUint8(offset); 53 | offset += 1; 54 | update.owner = data.extractAddress(offset); 55 | offset += 20; 56 | update.accountID = data.extractUint32(offset); 57 | offset += 4; 58 | update.feeTokenID = data.extractUint32(offset); 59 | offset += 4; 60 | update.fee = fromFloat( 61 | data.extractUint16(offset), 62 | Constants.Float16Encoding 63 | ); 64 | offset += 2; 65 | const publicKey = data.extractData(offset, 32); 66 | offset += 32; 67 | update.nonce = data.extractUint32(offset); 68 | offset += 4; 69 | 70 | // Unpack the public key 71 | const unpacked = EdDSA.unpack(publicKey); 72 | update.publicKeyX = unpacked.publicKeyX; 73 | update.publicKeyY = unpacked.publicKeyY; 74 | 75 | return update; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/request_processors/appkey_update_processor.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { Bitstream } from "../bitstream"; 3 | import { Constants } from "../constants"; 4 | import { EdDSA } from "../eddsa"; 5 | import { fromFloat } from "../float"; 6 | import { BlockContext, ExchangeState } from "../types"; 7 | 8 | interface AppKeyUpdate { 9 | owner?: string; 10 | accountID?: number; 11 | feeTokenID?: number; 12 | fee?: BN; 13 | validUntil?: number; 14 | nonce?: number; 15 | } 16 | 17 | /** 18 | * Processes account update requests. 19 | */ 20 | export class AppKeyUpdateProcessor { 21 | public static process( 22 | state: ExchangeState, 23 | block: BlockContext, 24 | txData: Bitstream 25 | ) { 26 | const update = AppKeyUpdateProcessor.extractData(txData); 27 | 28 | const accountID = state.ownerToAccountId[update.owner]; 29 | console.log("AppKeyUpdateProcessor", update.owner, accountID); 30 | 31 | const account = state.getAccount(accountID); 32 | account.owner = update.owner; 33 | account.nonce++; 34 | 35 | const balance = account.getBalance(update.feeTokenID); 36 | balance.balance.isub(update.fee); 37 | 38 | const operator = state.getAccount(block.operatorAccountID); 39 | const balanceO = operator.getBalance(update.feeTokenID); 40 | balanceO.balance.iadd(update.fee); 41 | 42 | return update; 43 | } 44 | 45 | public static extractData(data: Bitstream) { 46 | const update: AppKeyUpdate = {}; 47 | let offset = 0; 48 | 49 | const updateType = data.extractUint8(offset); 50 | offset += 1; 51 | update.owner = data.extractAddress(offset); 52 | offset += 20; 53 | update.accountID = data.extractUint32(offset); 54 | offset += 4; 55 | update.feeTokenID = data.extractUint32(offset); 56 | offset += 4; 57 | update.fee = fromFloat( 58 | data.extractUint16(offset), 59 | Constants.Float16Encoding 60 | ); 61 | offset += 2; 62 | update.nonce = data.extractUint32(offset); 63 | offset += 4; 64 | 65 | return update; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/request_processors/deposit_processor.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { Bitstream } from "../bitstream"; 3 | import { Constants } from "../constants"; 4 | import { Account, BlockContext, ExchangeState } from "../types"; 5 | 6 | interface Deposit { 7 | to?: string; 8 | toAccountID?: number; 9 | tokenID?: number; 10 | amount?: BN; 11 | type?: number; 12 | } 13 | 14 | /** 15 | * Processes deposit requests. 16 | */ 17 | export class DepositProcessor { 18 | public static process( 19 | state: ExchangeState, 20 | block: BlockContext, 21 | txData: Bitstream 22 | ) { 23 | const deposit = this.extractData(txData); 24 | 25 | const account = state.getAccount(deposit.toAccountID); 26 | account.owner = deposit.to; 27 | 28 | state.ownerToAccountId[account.owner] = deposit.toAccountID; 29 | 30 | const balance = account.getBalance(deposit.tokenID); 31 | balance.balance.iadd(deposit.amount); 32 | 33 | return deposit; 34 | } 35 | 36 | public static extractData(data: Bitstream) { 37 | const deposit: Deposit = {}; 38 | let offset = 0; 39 | 40 | // Read in the deposit data 41 | deposit.type = data.extractUint8(offset); 42 | offset += 1; 43 | 44 | deposit.to = data.extractAddress(offset); 45 | offset += 20; 46 | deposit.toAccountID = data.extractUint32(offset); 47 | offset += 4; 48 | deposit.tokenID = data.extractUint32(offset); 49 | offset += 4; 50 | deposit.amount = data.extractUint248(offset); 51 | offset += 31; 52 | 53 | return deposit; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/request_processors/order_cancel_processor.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { Bitstream } from "../bitstream"; 3 | import { Constants } from "../constants"; 4 | import { EdDSA } from "../eddsa"; 5 | import { fromFloat } from "../float"; 6 | import { BlockContext, ExchangeState } from "../types"; 7 | interface OrderCancel { 8 | owner?: string; 9 | accountID?: number; 10 | tokenID?: number; 11 | storageID?: number; 12 | feeTokenID?: number; 13 | fee?: BN; 14 | } 15 | 16 | /** 17 | * Processes account update requests. 18 | */ 19 | export class OrderCancelProcessor { 20 | public static process( 21 | state: ExchangeState, 22 | block: BlockContext, 23 | txData: Bitstream 24 | ) { 25 | const update = OrderCancelProcessor.extractData(txData); 26 | 27 | const account = state.getAccount(update.accountID); 28 | 29 | const balance = account.getBalance(update.feeTokenID); 30 | balance.balance.isub(update.fee); 31 | 32 | const storage = account 33 | .getStorage(update.storageID); 34 | 35 | console.log("OrderCancelProcessor::storage ", storage); 36 | console.log("OrderCancelProcessor:update ", update); 37 | storage.storageID = update.storageID; 38 | storage.cancelled = 1; 39 | 40 | const operator = state.getAccount(block.operatorAccountID); 41 | const balanceO = operator.getBalance(update.feeTokenID); 42 | balanceO.balance.iadd(update.fee); 43 | 44 | return update; 45 | } 46 | 47 | public static extractData(dataIn: Bitstream) { 48 | const orderCancel: OrderCancel = {}; 49 | 50 | let dataInString = dataIn.getData(); 51 | let data = new Bitstream(dataInString.slice(3)); 52 | 53 | let offset = 0; 54 | 55 | orderCancel.owner = data.extractAddress(offset); 56 | offset += 20; 57 | orderCancel.accountID = data.extractUint32(offset); 58 | offset += 4; 59 | orderCancel.tokenID = data.extractUint32(offset); 60 | offset += 4; 61 | orderCancel.storageID = data.extractUint32(offset); 62 | offset += 4; 63 | orderCancel.feeTokenID = data.extractUint32(offset); 64 | offset += 4; 65 | orderCancel.fee = fromFloat( 66 | data.extractUint16(offset), 67 | Constants.Float16Encoding 68 | ); 69 | offset += 2; 70 | return orderCancel; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/request_processors/transfer_processor.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { Bitstream } from "../bitstream"; 3 | import { Constants } from "../constants"; 4 | import { fromFloat } from "../float"; 5 | import { BlockContext, ExchangeState } from "../types"; 6 | 7 | interface Transfer { 8 | accountFromID?: number; 9 | accountToID?: number; 10 | tokenID?: number; 11 | amount?: BN; 12 | feeTokenID?: number; 13 | fee?: BN; 14 | validUntil?: number; 15 | storageID?: number; 16 | from?: string; 17 | to?: string; 18 | data?: string; 19 | } 20 | 21 | /** 22 | * Processes transfer requests. 23 | */ 24 | export class TransferProcessor { 25 | public static process( 26 | state: ExchangeState, 27 | block: BlockContext, 28 | txData: Bitstream 29 | ) { 30 | const transfer = this.extractData(txData); 31 | 32 | const from = state.getAccount(transfer.accountFromID); 33 | const to = state.getAccount(transfer.accountToID); 34 | if (transfer.to !== Constants.zeroAddress) { 35 | to.owner = transfer.to; 36 | } 37 | 38 | from.getBalance(transfer.tokenID).balance.isub(transfer.amount); 39 | to.getBalance(transfer.tokenID).balance.iadd(transfer.amount); 40 | 41 | from.getBalance(transfer.feeTokenID).balance.isub(transfer.fee); 42 | 43 | // Nonce 44 | const storage = from 45 | .getStorage(transfer.storageID); 46 | storage.storageID = transfer.storageID; 47 | storage.data = new BN(1); 48 | 49 | const operator = state.getAccount(block.operatorAccountID); 50 | operator.getBalance(transfer.feeTokenID).balance.iadd(transfer.fee); 51 | 52 | return transfer; 53 | } 54 | 55 | public static extractData(dataIn: Bitstream) { 56 | const transfer: Transfer = {}; 57 | 58 | let dataInString = dataIn.getData(); 59 | let data = new Bitstream(dataInString.slice(3)); 60 | 61 | let offset = 0; 62 | 63 | // Check that this is a conditional update 64 | const transferType = data.extractUint8(offset); 65 | offset += 1; 66 | 67 | transfer.accountFromID = data.extractUint32(offset); 68 | offset += 4; 69 | transfer.accountToID = data.extractUint32(offset); 70 | offset += 4; 71 | 72 | transfer.tokenID = data.extractUint32(offset); 73 | offset += 4; 74 | transfer.amount = fromFloat( 75 | data.extractUint32(offset), 76 | Constants.Float32Encoding 77 | ); 78 | offset += 4; 79 | 80 | transfer.feeTokenID = data.extractUint32(offset); 81 | offset += 4; 82 | transfer.fee = fromFloat( 83 | data.extractUint16(offset), 84 | Constants.Float16Encoding 85 | ); 86 | offset += 2; 87 | transfer.storageID = data.extractUint32(offset); 88 | offset += 4; 89 | transfer.to = data.extractAddress(offset); 90 | offset += 20; 91 | transfer.from = data.extractAddress(offset); 92 | offset += 20; 93 | 94 | return transfer; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/src/request_processors/withdrawal_processor.ts: -------------------------------------------------------------------------------- 1 | import BN from "bn.js"; 2 | import { Bitstream } from "../bitstream"; 3 | import { Constants } from "../constants"; 4 | import { fromFloat } from "../float"; 5 | import { BlockContext, ExchangeState } from "../types"; 6 | 7 | interface Withdrawal { 8 | type?: number; 9 | from?: string; 10 | fromAccountID?: number; 11 | tokenID?: number; 12 | amount?: BN; 13 | feeTokenID?: number; 14 | fee?: BN; 15 | to?: string; 16 | onchainDataHash?: string; 17 | minGas?: number; 18 | validUntil?: number; 19 | storageID?: number; 20 | } 21 | 22 | /** 23 | * Processes withdrawal requests. 24 | */ 25 | export class WithdrawalProcessor { 26 | public static process( 27 | state: ExchangeState, 28 | block: BlockContext, 29 | txData: Bitstream 30 | ) { 31 | const withdrawal = this.extractData(txData); 32 | 33 | const account = state.getAccount(withdrawal.fromAccountID); 34 | account.getBalance(withdrawal.tokenID).balance.isub(withdrawal.amount); 35 | account.getBalance(withdrawal.feeTokenID).balance.isub(withdrawal.fee); 36 | 37 | const operator = state.getAccount(block.operatorAccountID); 38 | operator.getBalance(withdrawal.feeTokenID).balance.iadd(withdrawal.fee); 39 | 40 | if (withdrawal.type === 0 || withdrawal.type === 1) { 41 | // Nonce 42 | const storage = account 43 | .getStorage(withdrawal.storageID); 44 | storage.storageID = withdrawal.storageID; 45 | storage.data = new BN(1); 46 | } 47 | 48 | return withdrawal; 49 | } 50 | 51 | public static extractData(data: Bitstream) { 52 | const withdrawal: Withdrawal = {}; 53 | let offset = 0; 54 | 55 | withdrawal.type = data.extractUint8(offset); 56 | offset += 1; 57 | withdrawal.from = data.extractAddress(offset); 58 | offset += 20; 59 | withdrawal.fromAccountID = data.extractUint32(offset); 60 | offset += 4; 61 | 62 | withdrawal.tokenID = data.extractUint32(offset); 63 | offset += 4; 64 | 65 | withdrawal.feeTokenID = data.extractUint32(offset); 66 | offset += 4; 67 | withdrawal.fee = fromFloat( 68 | data.extractUint16(offset), 69 | Constants.Float16Encoding 70 | ); 71 | offset += 2; 72 | withdrawal.storageID = data.extractUint32(offset); 73 | offset += 4; 74 | withdrawal.onchainDataHash = data.extractData(offset, 20); 75 | offset += 20; 76 | 77 | return withdrawal; 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packages/loopring_v3.js/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "esModuleInterop": true, 5 | "outDir": "build", 6 | "sourceMap": true, 7 | "inlineSources": true, 8 | "module": "commonjs", 9 | "target": "es6", 10 | "lib": ["es6"], 11 | "allowJs": true 12 | }, 13 | "include": [ 14 | "./node_modules/types-bn/index.d.ts", 15 | "./globals.d.ts", 16 | "src/**/*", 17 | "index.ts" 18 | ], 19 | "exclude": [] 20 | } 21 | -------------------------------------------------------------------------------- /packages/loopring_v3/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: "@typescript-eslint/parser", 3 | plugins: ["@typescript-eslint"], 4 | extends: ["plugin:prettier/recommended"] 5 | }; 6 | -------------------------------------------------------------------------------- /packages/loopring_v3/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | build/ 3 | transpiled/ 4 | ABI/ 5 | ethsnarks/ 6 | coverage/ 7 | coverage.json 8 | ABI/ 9 | keys/ 10 | blocks/ 11 | .DS_Store 12 | .node-* 13 | *.log 14 | state_*.json 15 | withdraw_proof.json 16 | .env 17 | ganache_account_keys.txt 18 | __pycache__ 19 | *.pyc 20 | .idea/ 21 | genkeys/ 22 | EDDSA_KeyPair.json 23 | *.deployed 24 | .tmp.* -------------------------------------------------------------------------------- /packages/loopring_v3/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | } -------------------------------------------------------------------------------- /packages/loopring_v3/.solcover.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | skipFiles: ["lib/Poseidon.sol"] 3 | }; 4 | -------------------------------------------------------------------------------- /packages/loopring_v3/.soliumignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | contracts/Migrations.sol 3 | contracts/thirdparty 4 | -------------------------------------------------------------------------------- /packages/loopring_v3/.soliumrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "solium:recommended", 3 | "plugins": ["security"], 4 | "rules": { 5 | "security/no-inline-assembly": "off", 6 | "security/no-block-members": "off", 7 | "security/no-low-level-calls": "off", 8 | "value-in-payable": "off", 9 | "no-empty-blocks": "off", 10 | "visibility-first": "error", 11 | "quotes": ["error", "double"], 12 | "indentation": ["error", 4], 13 | "linebreak-style": ["error", "unix"] 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/loopring_v3/.travis.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | include: 3 | # use the built in venv for linux builds 4 | - os: linux 5 | language: python 6 | python: 3.6 7 | - os: osx 8 | language: cpp 9 | install: 10 | - ./install 11 | script: 12 | - make 13 | -------------------------------------------------------------------------------- /packages/loopring_v3/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9) 2 | 3 | set (CMAKE_CXX_STANDARD 11) 4 | 5 | project(snarks-dex) 6 | add_subdirectory(ethsnarks ethsnarks EXCLUDE_FROM_ALL) 7 | add_subdirectory(circuit circuit) 8 | -------------------------------------------------------------------------------- /packages/loopring_v3/Makefile: -------------------------------------------------------------------------------- 1 | ROOT_DIR := $(shell dirname $(realpath $(MAKEFILE_LIST))) 2 | PYTHON=python3 3 | 4 | # CMAKE_TYPE := cmake-release 5 | # CMAKE_TYPE := cmake-openmp-performance 6 | CMAKE_TYPE := cmake-openmp-debug 7 | 8 | ifeq ($(ZKP_WORKER_MODE), 1) 9 | CMAKE_TYPE := cmake-openmp-release 10 | endif 11 | 12 | ifeq ($(OS),Windows_NT) 13 | detected_OS := Windows 14 | DLL_EXT := .dll 15 | else 16 | detected_OS := $(shell uname -s) 17 | ifeq ($(detected_OS),Darwin) 18 | DLL_EXT := .dylib 19 | export LD_LIBRARY_PATH := /usr/local/opt/openssl/lib:/usr/local/opt/gmp/lib:$(LD_LIBRARY_PATH) 20 | export LIBRARY_PATH := /usr/local/opt/gmp/lib:$(LIBRARY_PATH) 21 | export CPATH := /usr/local/opt/openssl/include:/usr/local/opt/gmp/include:/usr/local/opt/boost/include:$(CPATH) 22 | export PKG_CONFIG_PATH := /usr/local/opt/openssl/lib/pkgconfig:$(PKG_CONFIG_PATH) 23 | CMAKE_TYPE := cmake-openmp-debug 24 | else 25 | DLL_EXT := .so 26 | endif 27 | endif 28 | 29 | all: test 30 | 31 | test: build/circuit/dex_circuit 32 | 33 | build/circuit/dex_circuit: $(CMAKE_TYPE) 34 | make -C build 35 | mkdir -p keys 36 | rm -rf ./keys/* 37 | 38 | cmake-debug: 39 | mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. 40 | 41 | cmake-release: 42 | mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DZKP_WORKER_MODE=1 .. 43 | 44 | cmake-openmp-debug: 45 | mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Debug .. 46 | 47 | cmake-openmp-release: 48 | mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DMULTICORE=1 -DZKP_WORKER_MODE=1 .. 49 | 50 | cmake-openmp-performance: 51 | mkdir -p build && cd build && cmake -DCMAKE_BUILD_TYPE=Release -DMULTICORE=1 -DPERFORMANCE=1 .. 52 | 53 | git-submodules: 54 | git submodule update --init --recursive --remote 55 | -------------------------------------------------------------------------------- /packages/loopring_v3/README.md: -------------------------------------------------------------------------------- 1 | # DeGate Protocol v0.1.0 2 | 3 | ## Build 4 | 5 | If you are using a Mac, you will need to (re)install the commandline tool: 6 | 7 | ``` 8 | sudo rm -rf /Library/Developer/CommandLineTools 9 | xcode-select --install 10 | 11 | ``` 12 | 13 | Then you may also need to install "lgmpxx": 14 | 15 | - Download the source from https://gmplib.org/download/gmp/gmp-6.2.0.tar.lz 16 | - unzip it using (lzip - `brew install lzip`) :`tar -xf gmp-6.2.0.tar.lz` 17 | - install it: 18 | 19 | ``` 20 | ./configure --prefix=/usr/local --enable-cxx 21 | make 22 | make check 23 | sudo make install 24 | ``` 25 | 26 | Please use node v14.15.5. 27 | - `git submodule update --init --recursive` execute in the protocols directory 28 | - `npm install` 29 | - `npm run build` or `npm run compile` or `npm run watch`. 30 | 31 | ### Circuits 32 | 33 | The circuit tests can be run with `npm run testc`. A single test can be run with `npm run test-circuits `. 34 | 35 | ## Run Unit Tests 36 | 37 | - please make sure you run `npm run build` for the first time. 38 | - run `npm run ganache` from project's root directory in terminal. 39 | - run `npm run test` from project's root directory in another terminal window. 40 | - run single test: `npm run test -- transpiled/test/xxx.js` 41 | - print info logs in tests: `npm run test -- -i` 42 | - print more detailed debug logs in tests: `npm run test -- -x` 43 | 44 | Running all tests takes around 1 hour on a modern PC with a CPU with 4 cores. Creating proofs is computationaly heavy and takes time even when multi-threading is used. Run individual tests when you can. 45 | 46 | Verifier/Prover keys are cached in the `keys` folder. When running `make` these keys are automatically deleted so they cannot be outdated. 47 | 48 | ## Contract Deployment 49 | 50 | - development network: `npm run migrate-dev` 51 | - ropsten network: `npm run migrate-ropsten` 52 | - main network: `npm run migrate` 53 | 54 | If you have installed truffle globally, you can run: 55 | 56 | `npm run transpile && truffle migrate --network --reset --dry-run` 57 | 58 | Replace network with `development`, `live`, `ropsten`, `koven`, etc. -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/.clang-format: -------------------------------------------------------------------------------- 1 | Language: Cpp 2 | BasedOnStyle: LLVM 3 | IndentWidth: 4 4 | ContinuationIndentWidth: 2 5 | ColumnLimit: 120 6 | BinPackArguments: false 7 | SortIncludes: false 8 | BinPackParameters: false 9 | AlignAfterOpenBracket: AlwaysBreak 10 | IndentCaseLabels: true 11 | AllowAllParametersOfDeclarationOnNextLine: false 12 | AllowShortBlocksOnASingleLine: Never 13 | AllowShortCaseLabelsOnASingleLine: false 14 | AllowShortIfStatementsOnASingleLine: false 15 | AllowShortFunctionsOnASingleLine: false 16 | AllowShortLoopsOnASingleLine: false 17 | BreakConstructorInitializersBeforeComma: false 18 | BreakConstructorInitializers: BeforeColon 19 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 20 | BraceWrapping: 21 | AfterClass: true 22 | AfterControlStatement: true 23 | AfterEnum: true 24 | AfterFunction: true 25 | AfterNamespace: true 26 | AfterObjCDeclaration: true 27 | AfterStruct: true 28 | AfterUnion: true 29 | BeforeCatch: true 30 | BeforeElse: true 31 | IndentBraces: false 32 | BreakBeforeBraces: Custom -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.9) 2 | project(circuit) 3 | 4 | set( 5 | CURVE 6 | "MCL_BN128" 7 | CACHE 8 | STRING 9 | "Default curve: one of ALT_BN128, BN128, MCL_BN128, EDWARDS, MNT4, MNT6" 10 | ) 11 | 12 | if("${MULTICORE}") 13 | add_definitions(-DMULTICORE=1) 14 | endif() 15 | 16 | add_definitions(-DCURVE_${CURVE}) 17 | 18 | set(circuit_src_folder "./") 19 | 20 | if("${ZKP_WORKER_MODE}") 21 | add_definitions(-DZKP_WORKER_MODE=1) 22 | set( PROJECT_LINK_LIBS 23 | ethsnarks_jubjub 24 | rdkafka 25 | rdkafka++ 26 | # aws-cpp-sdk-core 27 | # aws-cpp-sdk-s3 28 | ) 29 | else() 30 | set( PROJECT_LINK_LIBS 31 | ethsnarks_jubjub 32 | ) 33 | endif() 34 | 35 | add_executable(dex_circuit "${circuit_src_folder}/main.cpp") 36 | target_link_libraries(dex_circuit ${PROJECT_LINK_LIBS}) 37 | if("${PERFORMANCE}") 38 | set_target_properties(dex_circuit PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) 39 | endif() 40 | 41 | file(GLOB test_filenames 42 | "${circuit_src_folder}/test/*.cpp" 43 | ) 44 | 45 | add_executable(dex_circuit_tests ${test_filenames}) 46 | target_link_libraries(dex_circuit_tests ethsnarks_jubjub) 47 | 48 | # # zkpproxy 49 | # add_executable(dex_proxy "${circuit_src_folder}/zkpproxy.cpp") 50 | # target_link_libraries(dex_proxy ${PROJECT_LINK_LIBS}) 51 | # if("${PERFORMANCE}") 52 | # set_target_properties(dex_proxy PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) 53 | # endif() 54 | 55 | 56 | if("${GPU_PROVE}") 57 | add_definitions(-DGPU_PROVE=1) 58 | enable_language(CUDA) 59 | target_compile_features(prover_reference_functions PUBLIC cxx_std_11) 60 | add_executable(dex_circuit_gpu "${circuit_src_folder}/cuda_prover/cuda_prover.cu") 61 | target_link_libraries(dex_circuit_gpu prover_reference_functions) 62 | endif() 63 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/Circuits/Circuit.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | #ifndef _CIRCUIT_H_ 4 | #define _CIRCUIT_H_ 5 | 6 | #include "ethsnarks.hpp" 7 | #include "../Utils/Data.h" 8 | 9 | using namespace ethsnarks; 10 | 11 | namespace Loopring 12 | { 13 | 14 | class Circuit : public GadgetT 15 | { 16 | public: 17 | Circuit( // 18 | libsnark::protoboard &pb, 19 | const std::string &annotation_prefix) 20 | : GadgetT(pb, annotation_prefix){}; 21 | virtual ~Circuit(){}; 22 | virtual void generateConstraints(unsigned int blockSize) = 0; 23 | virtual bool generateWitness(const json &input) = 0; 24 | virtual unsigned int getBlockType() = 0; 25 | virtual unsigned int getBlockSize() = 0; 26 | virtual void printInfo() = 0; 27 | 28 | libsnark::protoboard &getPb() 29 | { 30 | return pb; 31 | } 32 | }; 33 | 34 | } // namespace Loopring 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/Circuits/NoopCircuit.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | #ifndef _NOOPCIRCUIT_H_ 5 | #define _NOOPCIRCUIT_H_ 6 | 7 | #include "Circuit.h" 8 | #include "../Utils/Constants.h" 9 | #include "../Utils/Data.h" 10 | 11 | #include "ethsnarks.hpp" 12 | #include "utils.hpp" 13 | 14 | using namespace ethsnarks; 15 | 16 | namespace Loopring 17 | { 18 | 19 | class NoopCircuit : public BaseTransactionCircuit 20 | { 21 | public: 22 | DualVariableGadget typeTx; 23 | DualVariableGadget typeTxPad; 24 | NoopCircuit( // 25 | ProtoboardT &pb, 26 | const TransactionState &state, 27 | const std::string &prefix) 28 | : BaseTransactionCircuit(pb, state, prefix), 29 | typeTx(pb, NUM_BITS_TX_TYPE, FMT(prefix, ".typeTx")), 30 | typeTxPad(pb, NUM_BITS_BIT, FMT(prefix, ".typeTxPad")) 31 | { 32 | LOG(LogDebug, "in NoopCircuit", ""); 33 | // No signatures needed 34 | setOutput(TXV_SIGNATURE_REQUIRED_A, state.constants._0); 35 | setOutput(TXV_SIGNATURE_REQUIRED_B, state.constants._0); 36 | } 37 | 38 | void generate_r1cs_witness() 39 | { 40 | LOG(LogDebug, "in NoopCircuit", "generate_r1cs_witness"); 41 | typeTx.generate_r1cs_witness(pb, ethsnarks::FieldT(int(Loopring::TransactionType::Noop))); 42 | typeTxPad.generate_r1cs_witness(pb, ethsnarks::FieldT(0)); 43 | } 44 | 45 | void generate_r1cs_constraints() 46 | { 47 | LOG(LogDebug, "in NoopCircuit", "generate_r1cs_constraints"); 48 | typeTx.generate_r1cs_constraints(true); 49 | typeTxPad.generate_r1cs_constraints(true); 50 | } 51 | 52 | const VariableArrayT getPublicData() const 53 | { 54 | return flattenReverse({ 55 | typeTx.bits, 56 | typeTxPad.bits 57 | }); 58 | } 59 | }; 60 | 61 | } // namespace Loopring 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/ThirdParty/BigIntHeader.hpp: -------------------------------------------------------------------------------- 1 | #define BIG_INT_UTILITY_FUNCTIONS_HPP 2 | #define BIG_INT_CONSTRUCTORS_HPP 3 | #define BIG_INT_CONVERSION_FUNCTIONS_HPP 4 | #define BIG_INT_ASSIGNMENT_OPERATORS_HPP 5 | #define BIG_INT_UNARY_ARITHMETIC_OPERATORS_HPP 6 | #define BIG_INT_RELATIONAL_OPERATORS_HPP 7 | #define BIG_INT_MATH_FUNCTIONS_HPP 8 | #define BIG_INT_BINARY_ARITHMETIC_OPERATORS_HPP 9 | #define BIG_INT_ARITHMETIC_ASSIGNMENT_OPERATORS_HPP 10 | #define BIG_INT_INCREMENT_DECREMENT_OPERATORS_HPP 11 | #define BIG_INT_IO_STREAM_OPERATORS_HPP 12 | #include "BigInt.hpp" -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/buildCircuit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd .. 4 | 5 | ##ethsnarks 6 | git submodule update --init --recursive 7 | 8 | make ZKP_WORKER_MODE=1 9 | 10 | rm -rf circuit/build && mv build circuit/ 11 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # FROM registry.bihutest.com/base/zkp-base:1.0.0-1 2 | FROM registry.degate.space/base/zkp-base:1.0.0-1 3 | 4 | ARG VERSION 5 | 6 | ENV LC_ALL C.UTF-8 7 | ENV LANG C.UTF-8 8 | 9 | ADD ./build/ /degate/zkpworker/build/ 10 | ADD docker/entrypoint.sh /degate/zkpworker/ 11 | ADD docker/entrypoint-host.sh /degate/zkpworker/ 12 | ADD module_config.tpl /data/module_config.tpl 13 | RUN chmod +x /degate/zkpworker/*.sh 14 | RUN mkdir -p /degate/zkpworker/s3_data 15 | 16 | WORKDIR /degate/zkpworker/ 17 | 18 | ENTRYPOINT ["./entrypoint.sh"] 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/docker/entrypoint-host.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | mkdir -p /degate/zkpworker/s3_data 4 | cp /data/etc/*.json /degate/zkpworker/ 5 | 6 | /degate/zkpworker/build/circuit/dex_circuit -server /degate/zkpworker/protoBlock.json 9090 7 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/docker/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | request_args=`cat /tmp/request_args` 4 | #echo ${request_args}protoBlock.json?raw 5 | #curl ${request_args}protoBlock.json?raw > /degate/zkpworker/protoBlock.json 6 | #curl ${request_args}worker_config.json?raw > /degate/zkpworker/worker_config.json 7 | cp /tmp/module.config /degate/zkpworker/protoBlock.json 8 | mkdir -p /degate/zkpworker/s3_data 9 | 10 | ./build/circuit/dex_circuit -server /degate/zkpworker/protoBlock.json 9090 11 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | com.degate 6 | zkp-worker 7 | 0.0.1-${BUILD_NUMBER} 8 | 9 | 10 | 11 | nexus-releases 12 | Nexus Release Repository 13 | https://nexus.bihutest.com/repository/maven-releases/ 14 | 15 | 16 | nexus-snapshots 17 | Nexus Snapshot Repository 18 | https://nexus.bihutest.com/repository/maven-snapshots/ 19 | 20 | 21 | 22 | 23 | 24 | 25 | exec-maven-plugin 26 | 1.6.0 27 | org.codehaus.mojo 28 | 29 | 30 | build dex_circuit 31 | package 32 | 33 | exec 34 | 35 | 36 | bash 37 | buildCircuit.sh 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/test/data/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "num_threads":4, 3 | "fft":"recursive", 4 | "smt":false, 5 | "swapAB":true, 6 | "multi_exp_c":0, 7 | "multi_exp_prefetch_locality":0, 8 | "prefetch_stride":128, 9 | "multi_exp_look_ahead":1 10 | } -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/test/data/protoBlock.json: -------------------------------------------------------------------------------- 1 | { 2 | "blockType": 0, 3 | "blockSize": 8 4 | } -------------------------------------------------------------------------------- /packages/loopring_v3/circuit/test/main.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file 2 | #include "../ThirdParty/catch.hpp" 3 | #include "../ThirdParty/BigInt.hpp" 4 | #include "ethsnarks.hpp" 5 | 6 | struct Initialize 7 | { 8 | Initialize() 9 | { 10 | ethsnarks::ppT::init_public_params(); 11 | srand(time(NULL)); 12 | } 13 | } initialize; -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/Migrations.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | contract Migrations 6 | { 7 | address public owner; 8 | uint public last_completed_migration; 9 | 10 | modifier restricted() 11 | { 12 | if (msg.sender == owner) { 13 | _; 14 | } 15 | } 16 | 17 | constructor() 18 | { 19 | owner = msg.sender; 20 | } 21 | 22 | function setCompleted(uint completed) 23 | public 24 | restricted 25 | { 26 | last_completed_migration = completed; 27 | } 28 | 29 | function upgrade(address newAddress) 30 | public 31 | restricted 32 | { 33 | Migrations upgraded = Migrations(newAddress); 34 | upgraded.setCompleted(last_completed_migration); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/access/DelayedOwner.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | 6 | import "../../lib/Claimable.sol"; 7 | import "./DelayedTransaction.sol"; 8 | 9 | 10 | /// @title DelayedOwner 11 | /// @author Brecht Devos - 12 | contract DelayedOwner is DelayedTransaction, Claimable 13 | { 14 | address public defaultContract; 15 | 16 | event FunctionDelayUpdate( 17 | bytes4 functionSelector, 18 | uint delay 19 | ); 20 | 21 | constructor( 22 | address _defaultContract, 23 | uint _timeToLive 24 | ) 25 | DelayedTransaction(_timeToLive) 26 | { 27 | require(_defaultContract != address(0), "INVALID_ADDRESS"); 28 | 29 | defaultContract = _defaultContract; 30 | } 31 | 32 | receive() 33 | external 34 | // nonReentrant 35 | payable 36 | { 37 | // Don't do anything when receiving ETH 38 | } 39 | 40 | fallback() 41 | external 42 | nonReentrant 43 | payable 44 | { 45 | // Don't do anything if msg.sender isn't the owner 46 | if (msg.sender != owner) { 47 | return; 48 | } 49 | transactInternal(defaultContract, msg.value, msg.data); 50 | } 51 | 52 | function isAuthorizedForTransactions(address sender) 53 | internal 54 | override 55 | view 56 | returns (bool) 57 | { 58 | return sender == owner; 59 | } 60 | 61 | function setFunctionDelay( 62 | bytes4 functionSelector, 63 | uint delay 64 | ) 65 | internal 66 | { 67 | setFunctionDelay(defaultContract, functionSelector, delay); 68 | 69 | emit FunctionDelayUpdate(functionSelector, delay); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/access/IBlockReceiver.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | pragma experimental ABIEncoderV2; 6 | 7 | import "../../core/iface/ExchangeData.sol"; 8 | 9 | /// @title IBlockReceiver 10 | /// @author Brecht Devos - 11 | abstract contract IBlockReceiver 12 | { 13 | function beforeBlockSubmission( 14 | bytes calldata txsData, 15 | bytes calldata callbackData 16 | ) 17 | external 18 | virtual; 19 | } 20 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/access/SelectorBasedAccessManager.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | 6 | import "../../core/iface/IExchangeV3.sol"; 7 | import "../../lib/Claimable.sol"; 8 | import "../../thirdparty/BytesUtil.sol"; 9 | 10 | 11 | /// @title SelectorBasedAccessManager 12 | /// @author Daniel Wang - 13 | contract SelectorBasedAccessManager is Claimable 14 | { 15 | using BytesUtil for bytes; 16 | 17 | event PermissionUpdate( 18 | address indexed user, 19 | bytes4 indexed selector, 20 | bool allowed 21 | ); 22 | 23 | event TargetCalled( 24 | address target, 25 | bytes data 26 | ); 27 | 28 | address public immutable target; 29 | mapping(address => mapping(bytes4 => bool)) public permissions; 30 | 31 | modifier withAccess(bytes4 selector) 32 | { 33 | require(hasAccessTo(msg.sender, selector), "PERMISSION_DENIED"); 34 | _; 35 | } 36 | 37 | constructor(address _target) 38 | { 39 | require(_target != address(0), "ZERO_ADDRESS"); 40 | target = _target; 41 | } 42 | 43 | function grantAccess( 44 | address user, 45 | bytes4 selector, 46 | bool granted 47 | ) 48 | external 49 | onlyOwner 50 | { 51 | require(permissions[user][selector] != granted, "INVALID_VALUE"); 52 | permissions[user][selector] = granted; 53 | emit PermissionUpdate(user, selector, granted); 54 | } 55 | 56 | receive() payable external {} 57 | 58 | fallback() 59 | payable 60 | external 61 | { 62 | transact(msg.data); 63 | } 64 | 65 | function transact(bytes memory data) 66 | payable 67 | public 68 | withAccess(data.toBytes4(0)) 69 | { 70 | (bool success, bytes memory returnData) = target 71 | .call{value: msg.value}(data); 72 | 73 | if (!success) { 74 | assembly { revert(add(returnData, 32), mload(returnData)) } 75 | } 76 | 77 | emit TargetCalled(target, data); 78 | } 79 | 80 | function hasAccessTo(address user, bytes4 selector) 81 | public 82 | view 83 | returns (bool) 84 | { 85 | return user == owner || permissions[user][selector]; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/agents/AgentRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "../../core/iface/IAgentRegistry.sol"; 7 | import "../../lib/AddressSet.sol"; 8 | import "../../lib/Claimable.sol"; 9 | 10 | 11 | contract AgentRegistry is IAgentRegistry, AddressSet, Claimable 12 | { 13 | bytes32 internal constant UNIVERSAL_AGENTS = keccak256("__UNVERSAL_AGENTS__"); 14 | 15 | event AgentRegistered( 16 | address indexed user, 17 | address indexed agent, 18 | bool registered 19 | ); 20 | 21 | event TrustUniversalAgents( 22 | address indexed user, 23 | bool trust 24 | ); 25 | 26 | constructor() Claimable() {} 27 | 28 | function isAgent( 29 | address user, 30 | address agent 31 | ) 32 | external 33 | override 34 | view 35 | returns (bool) 36 | { 37 | return isUniversalAgent(agent) || isUserAgent(user, agent); 38 | } 39 | 40 | function isAgent( 41 | address[] calldata users, 42 | address agent 43 | ) 44 | external 45 | override 46 | view 47 | returns (bool) 48 | { 49 | if (isUniversalAgent(agent)) { 50 | return true; 51 | } 52 | for (uint i = 0; i < users.length; i++) { 53 | if (!isUserAgent(users[i], agent)) { 54 | return false; 55 | } 56 | } 57 | return true; 58 | } 59 | 60 | function registerUniversalAgent( 61 | address agent, 62 | bool toRegister 63 | ) 64 | external 65 | onlyOwner 66 | { 67 | registerInternal(UNIVERSAL_AGENTS, agent, toRegister); 68 | emit AgentRegistered(address(0), agent, toRegister); 69 | } 70 | 71 | function isUniversalAgent(address agent) 72 | public 73 | override 74 | view 75 | returns (bool) 76 | { 77 | return isAddressInSet(UNIVERSAL_AGENTS, agent); 78 | } 79 | 80 | function registerUserAgent( 81 | address agent, 82 | bool toRegister 83 | ) 84 | external 85 | { 86 | registerInternal(userKey(msg.sender), agent, toRegister); 87 | emit AgentRegistered(msg.sender, agent, toRegister); 88 | } 89 | 90 | function isUserAgent( 91 | address user, 92 | address agent 93 | ) 94 | public 95 | view 96 | returns (bool) 97 | { 98 | return isAddressInSet(userKey(user), agent); 99 | } 100 | 101 | function registerInternal( 102 | bytes32 key, 103 | address agent, 104 | bool toRegister 105 | ) 106 | private 107 | { 108 | require(agent != address(0), "ZERO_ADDRESS"); 109 | if (toRegister) { 110 | addAddressToSet(key, agent, false /* maintanList */); 111 | } else { 112 | removeAddressFromSet(key, agent); 113 | } 114 | } 115 | 116 | function userKey(address addr) 117 | private 118 | pure 119 | returns (bytes32) 120 | { 121 | return keccak256(abi.encodePacked("__AGENT__", addr)); 122 | } 123 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/agents/ForcedWithdrawalAgent.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | pragma experimental ABIEncoderV2; 6 | 7 | import "../../core/iface/IExchangeV3.sol"; 8 | import "../../lib/ReentrancyGuard.sol"; 9 | import "../../lib/OwnerManagable.sol"; 10 | import "../../lib/AddressUtil.sol"; 11 | import "../../lib/Drainable.sol"; 12 | 13 | /// @author Kongliang Zhong - 14 | contract ForcedWithdrawalAgent is ReentrancyGuard, OwnerManagable, Drainable 15 | { 16 | using AddressUtil for address; 17 | 18 | function canDrain(address /*drainer*/, address /*token*/) 19 | public 20 | override 21 | view 22 | returns (bool) { 23 | return msg.sender == owner || isManager(msg.sender); 24 | } 25 | 26 | function doForcedWithdrawalFor( 27 | address exchangeAddress, 28 | address from, 29 | address token, 30 | uint32 accountID 31 | ) 32 | external 33 | payable 34 | nonReentrant 35 | onlyOwnerOrManager 36 | { 37 | IExchangeV3(exchangeAddress).forceWithdraw{value: msg.value}(from, token, accountID); 38 | 39 | if (address(this).balance > 0) { 40 | drain(msg.sender, address(0)); 41 | } 42 | } 43 | 44 | receive() external payable { } 45 | } 46 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/compression/ZeroDecompressor.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title ZeroDecompressor 7 | /// @author Brecht Devos - 8 | /// @dev Easy decompressor that compresses runs of zeros. 9 | /// The format is very simple. Each entry consists of 10 | /// (uint16 numDataBytes, uint16 numZeroBytes) which will 11 | /// copy `numDataBytes` data bytes from `data` and will 12 | /// add an additional `numZeroBytes` after it. 13 | library ZeroDecompressor 14 | { 15 | function decompress( 16 | bytes calldata /*data*/, 17 | uint parameterIdx 18 | ) 19 | internal 20 | pure 21 | returns (bytes memory) 22 | { 23 | bytes memory uncompressed; 24 | uint offsetPos = 4 + 32 * parameterIdx; 25 | assembly { 26 | uncompressed := mload(0x40) 27 | let ptr := add(uncompressed, 32) 28 | let offset := add(4, calldataload(offsetPos)) 29 | let pos := add(offset, 4) 30 | let dataLength := add(calldataload(offset), pos) 31 | let tupple := 0 32 | let numDataBytes := 0 33 | let numZeroBytes := 0 34 | 35 | for {} lt(pos, dataLength) {} { 36 | tupple := and(calldataload(pos), 0xFFFFFFFF) 37 | numDataBytes := shr(16, tupple) 38 | numZeroBytes := and(tupple, 0xFFFF) 39 | calldatacopy(ptr, add(32, pos), numDataBytes) 40 | pos := add(pos, add(4, numDataBytes)) 41 | ptr := add(ptr, add(numDataBytes, numZeroBytes)) 42 | } 43 | 44 | // Store data length 45 | mstore(uncompressed, sub(sub(ptr, uncompressed), 32)) 46 | 47 | // Update free memory pointer 48 | mstore(0x40, add(ptr, 0x20)) 49 | } 50 | return uncompressed; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/migrate/MigrationToLoopringExchangeV2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | pragma experimental ABIEncoderV2; 5 | 6 | 7 | import "../../lib/ReentrancyGuard.sol"; 8 | import "../../lib/Drainable.sol"; 9 | 10 | abstract contract ILoopringV3Partial 11 | { 12 | function withdrawExchangeStake( 13 | uint exchangeId, 14 | address recipient, 15 | uint requestedAmount 16 | ) 17 | external 18 | virtual 19 | returns (uint amount); 20 | } 21 | 22 | /// @author Kongliang Zhong - 23 | /// @dev This contract enables an alternative approach of getting back assets from Loopring Exchange v1. 24 | /// Now you don't have to withdraw using merkle proofs (very expensive); 25 | /// instead, all assets will be distributed on Loopring Exchange v2 - Loopring's new zkRollup implementation. 26 | /// Please activate and unlock your address on https://exchange.loopring.io to claim your assets. 27 | contract MigrationToLoopringExchangeV2 is Drainable 28 | { 29 | function canDrain(address /*drainer*/, address /*token*/) 30 | public 31 | override 32 | view 33 | returns (bool) { 34 | return isMigrationOperator(); 35 | } 36 | 37 | function withdrawExchangeStake( 38 | address loopringV3, 39 | uint exchangeId, 40 | uint amount, 41 | address recipient 42 | ) 43 | external 44 | { 45 | require(isMigrationOperator(), "INVALID_SENDER"); 46 | ILoopringV3Partial(loopringV3).withdrawExchangeStake(exchangeId, recipient, amount); 47 | } 48 | 49 | function isMigrationOperator() internal view returns (bool) { 50 | return msg.sender == 0x4374D3d032B3c96785094ec9f384f07077792768; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/aux/token-sellers/ITokenSeller.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title ITokenSeller 7 | /// @dev Use this contract to sell tokenS for as many tokenB. 8 | /// @author Daniel Wang - 9 | interface ITokenSeller 10 | { 11 | /// @dev Sells all tokenS for tokenB 12 | /// @param tokenS The token or Ether (0x0) to sell. 13 | /// @param tokenB The token to buy. 14 | /// @return success True if success, false otherwise. 15 | function sellToken( 16 | address tokenS, 17 | address tokenB 18 | ) 19 | external 20 | payable 21 | returns (bool success); 22 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/core/iface/IAgentRegistry.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | interface IAgent{} 6 | 7 | abstract contract IAgentRegistry 8 | { 9 | /// @dev Returns whether an agent address is an agent of an account owner 10 | /// @param owner The account owner. 11 | /// @param agent The agent address 12 | /// @return True if the agent address is an agent for the account owner, else false 13 | function isAgent( 14 | address owner, 15 | address agent 16 | ) 17 | external 18 | virtual 19 | view 20 | returns (bool); 21 | 22 | /// @dev Returns whether an agent address is an agent of all account owners 23 | /// @param owners The account owners. 24 | /// @param agent The agent address 25 | /// @return True if the agent address is an agent for the account owner, else false 26 | function isAgent( 27 | address[] calldata owners, 28 | address agent 29 | ) 30 | external 31 | virtual 32 | view 33 | returns (bool); 34 | 35 | /// @dev Returns whether an agent address is a universal agent. 36 | /// @param agent The agent address 37 | /// @return True if the agent address is a universal agent, else false 38 | function isUniversalAgent(address agent) 39 | public 40 | virtual 41 | view 42 | returns (bool); 43 | } 44 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/core/iface/IBlockVerifier.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | pragma experimental ABIEncoderV2; 6 | 7 | import "../../lib/Claimable.sol"; 8 | 9 | 10 | /// @title IBlockVerifier 11 | /// @author Brecht Devos - 12 | abstract contract IBlockVerifier is Claimable 13 | { 14 | // -- Events -- 15 | 16 | event CircuitRegistered( 17 | uint8 indexed blockType, 18 | uint16 blockSize, 19 | uint8 blockVersion 20 | ); 21 | 22 | event CircuitDisabled( 23 | uint8 indexed blockType, 24 | uint16 blockSize, 25 | uint8 blockVersion 26 | ); 27 | 28 | // -- Public functions -- 29 | 30 | /// @dev Verifies blocks with the given public data and proofs. 31 | /// Verifying a block makes sure all requests handled in the block 32 | /// are correctly handled by the operator. 33 | /// @param blockType The type of block 34 | /// @param blockSize The number of requests handled in the block 35 | /// @param blockVersion The block version (i.e. which circuit version needs to be used) 36 | /// @param publicInputs The hash of all the public data of the blocks 37 | /// @param proofs The ZK proofs proving that the blocks are correct 38 | /// @return True if the block is valid, false otherwise 39 | function verifyProofs( 40 | uint8 blockType, 41 | uint16 blockSize, 42 | uint8 blockVersion, 43 | uint[] calldata publicInputs, 44 | uint[] calldata proofs 45 | ) 46 | external 47 | virtual 48 | view 49 | returns (bool); 50 | 51 | /// @dev Checks if a circuit with the specified parameters is registered. 52 | /// @param blockType The type of the block 53 | /// @param blockSize The number of requests handled in the block 54 | /// @param blockVersion The block version (i.e. which circuit version needs to be used) 55 | /// @return True if the circuit is registered, false otherwise 56 | function isCircuitRegistered( 57 | uint8 blockType, 58 | uint16 blockSize, 59 | uint8 blockVersion 60 | ) 61 | external 62 | virtual 63 | view 64 | returns (bool); 65 | 66 | /// @dev Checks if a circuit can still be used to commit new blocks. 67 | /// @param blockType The type of the block 68 | /// @param blockSize The number of requests handled in the block 69 | /// @param blockVersion The block version (i.e. which circuit version needs to be used) 70 | /// @return True if the circuit is enabled, false otherwise 71 | function isCircuitEnabled( 72 | uint8 blockType, 73 | uint16 blockSize, 74 | uint8 blockVersion 75 | ) 76 | external 77 | virtual 78 | view 79 | returns (bool); 80 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/core/impl/libexchange/ExchangeAdmins.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | pragma experimental ABIEncoderV2; 6 | 7 | import "../../../lib/ERC20.sol"; 8 | import "../../../lib/ERC20SafeTransfer.sol"; 9 | import "../../../lib/MathUint.sol"; 10 | import "../../iface/ExchangeData.sol"; 11 | import "./ExchangeMode.sol"; 12 | 13 | 14 | /// @title ExchangeAdmins. 15 | /// @author Daniel Wang - 16 | /// @author Brecht Devos - 17 | library ExchangeAdmins 18 | { 19 | using ERC20SafeTransfer for address; 20 | using ExchangeMode for ExchangeData.State; 21 | using MathUint for uint; 22 | 23 | event MaxAgeDepositUntilWithdrawableChanged( 24 | address indexed exchangeAddr, 25 | uint32 oldValue, 26 | uint32 newValue 27 | ); 28 | 29 | function setMaxAgeDepositUntilWithdrawable( 30 | ExchangeData.State storage S, 31 | uint32 newValue 32 | ) 33 | public 34 | returns (uint32 oldValue) 35 | { 36 | require(!S.isInWithdrawalMode(), "INVALID_MODE"); 37 | require( 38 | newValue > 0 && 39 | newValue <= ExchangeData.MAX_AGE_DEPOSIT_UNTIL_WITHDRAWABLE_UPPERBOUND, 40 | "INVALID_VALUE" 41 | ); 42 | oldValue = S.maxAgeDepositUntilWithdrawable; 43 | S.maxAgeDepositUntilWithdrawable = newValue; 44 | 45 | emit MaxAgeDepositUntilWithdrawableChanged( 46 | address(this), 47 | oldValue, 48 | newValue 49 | ); 50 | } 51 | 52 | function withdrawExchangeStake( 53 | ExchangeData.State storage S, 54 | address recipient 55 | ) 56 | public 57 | returns (uint) 58 | { 59 | // Exchange needs to be shutdown 60 | require(S.isShutdown(), "EXCHANGE_NOT_SHUTDOWN"); 61 | require(!S.isInWithdrawalMode(), "CANNOT_BE_IN_WITHDRAWAL_MODE"); 62 | 63 | // Need to remain in shutdown for some time 64 | require(block.timestamp >= S.modeTime.shutdownModeStartTime + ExchangeData.MIN_TIME_IN_SHUTDOWN, "TOO_EARLY"); 65 | 66 | // Withdraw the complete stake 67 | uint amount = S.loopring.getExchangeStake(address(this)); 68 | return S.loopring.withdrawExchangeStake(recipient, amount); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/core/impl/libexchange/ExchangeGenesis.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | pragma experimental ABIEncoderV2; 6 | 7 | import "../../../lib/MathUint.sol"; 8 | import "../../iface/ExchangeData.sol"; 9 | import "../../iface/IAgentRegistry.sol"; 10 | import "../../iface/IBlockVerifier.sol"; 11 | import "../../iface/ILoopringV3.sol"; 12 | import "./ExchangeTokens.sol"; 13 | 14 | 15 | /// @title ExchangeGenesis. 16 | /// @author Daniel Wang - 17 | /// @author Brecht Devos - 18 | library ExchangeGenesis 19 | { 20 | using ExchangeTokens for ExchangeData.State; 21 | 22 | event ExchangeGenesisBlockInitialized( 23 | address loopringAddr, 24 | bytes32 genesisMerkleRoot, 25 | bytes32 genesisMerkleAssetRoot, 26 | bytes32 domainSeparator 27 | ); 28 | 29 | function initializeGenesisBlock( 30 | ExchangeData.State storage S, 31 | address _loopringAddr, 32 | bytes32 _genesisMerkleRoot, 33 | bytes32 _genesisMerkleAssetRoot, 34 | bytes32 _domainSeparator 35 | ) 36 | public 37 | { 38 | require(address(0) != _loopringAddr, "INVALID_LOOPRING_ADDRESS"); 39 | require(_genesisMerkleRoot != 0, "INVALID_GENESIS_MERKLE_ROOT"); 40 | require(_genesisMerkleAssetRoot != 0, "INVALID_GENESIS_MERKLE_ASSET_ROOT"); 41 | 42 | S.maxAgeDepositUntilWithdrawable = ExchangeData.MAX_AGE_DEPOSIT_UNTIL_WITHDRAWABLE_UPPERBOUND; 43 | S.DOMAIN_SEPARATOR = _domainSeparator; 44 | 45 | ILoopringV3 loopring = ILoopringV3(_loopringAddr); 46 | S.loopring = loopring; 47 | 48 | S.blockVerifier = IBlockVerifier(loopring.blockVerifierAddress()); 49 | 50 | S.merkleRoot = _genesisMerkleRoot; 51 | S.merkleAssetRoot = _genesisMerkleAssetRoot; 52 | S.blocks[0] = ExchangeData.BlockInfo(uint32(block.timestamp), bytes28(0)); 53 | S.numBlocks = 1; 54 | 55 | // Get the protocol fees for this exchange 56 | S.protocolFeeData.syncedAt = uint32(0); 57 | 58 | S.protocolFeeData.protocolFeeBips = S.loopring.protocolFeeBips(); 59 | S.protocolFeeData.previousProtocolFeeBips = S.protocolFeeData.protocolFeeBips; 60 | 61 | S.protocolFeeData.nextProtocolFeeBips = S.protocolFeeData.protocolFeeBips; 62 | S.protocolFeeData.executeTimeOfNextProtocolFeeBips = uint32(0); 63 | 64 | // Call these after the main state has been set up 65 | S.registerToken(address(0), true); 66 | S.registerToken(loopring.lrcAddress(), true); 67 | 68 | emit ExchangeGenesisBlockInitialized(_loopringAddr, _genesisMerkleRoot, _genesisMerkleAssetRoot, _domainSeparator); 69 | } 70 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/core/impl/libexchange/ExchangeMode.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | pragma experimental ABIEncoderV2; 6 | 7 | import "../../../lib/MathUint.sol"; 8 | import "../../iface/ExchangeData.sol"; 9 | 10 | 11 | /// @title ExchangeMode. 12 | /// @dev All methods in this lib are internal, therefore, there is no need 13 | /// to deploy this library independently. 14 | /// @author Brecht Devos - 15 | /// @author Daniel Wang - 16 | library ExchangeMode 17 | { 18 | using MathUint for uint; 19 | 20 | function isInWithdrawalMode( 21 | ExchangeData.State storage S 22 | ) 23 | internal // inline call 24 | view 25 | returns (bool result) 26 | { 27 | result = S.modeTime.withdrawalModeStartTime > 0; 28 | } 29 | 30 | function isShutdown( 31 | ExchangeData.State storage S 32 | ) 33 | internal // inline call 34 | view 35 | returns (bool) 36 | { 37 | return S.modeTime.shutdownModeStartTime > 0; 38 | } 39 | 40 | function getNumAvailableForcedSlots( 41 | ExchangeData.State storage S 42 | ) 43 | internal 44 | view 45 | returns (uint) 46 | { 47 | return ExchangeData.MAX_OPEN_FORCED_REQUESTS - S.numPendingForcedTransactions; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/core/impl/libexchange/ExchangeSignatures.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | pragma experimental ABIEncoderV2; 5 | 6 | import "../../../lib/SignatureUtil.sol"; 7 | import "../../iface/ExchangeData.sol"; 8 | 9 | 10 | /// @title ExchangeSignatures. 11 | /// @dev All methods in this lib are internal, therefore, there is no need 12 | /// to deploy this library independently. 13 | /// @author Brecht Devos - 14 | /// @author Daniel Wang - 15 | library ExchangeSignatures 16 | { 17 | using SignatureUtil for bytes32; 18 | 19 | function requireAuthorizedTx( 20 | ExchangeData.State storage S, 21 | address signer, 22 | bytes memory signature, 23 | bytes32 txHash 24 | ) 25 | internal // inline call 26 | { 27 | require(signer != address(0), "INVALID_SIGNER"); 28 | // Verify the signature if one is provided, otherwise fall back to an approved tx 29 | if (signature.length > 0) { 30 | require(txHash.verifySignature(signer, signature), "INVALID_SIGNATURE"); 31 | } else { 32 | require(S.approvedTx[signer][txHash], "TX_NOT_APPROVED"); 33 | delete S.approvedTx[signer][txHash]; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/AddressSet.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title AddressSet 7 | /// @author Daniel Wang - 8 | contract AddressSet 9 | { 10 | struct Set 11 | { 12 | address[] addresses; 13 | mapping (address => uint) positions; 14 | uint count; 15 | } 16 | mapping (bytes32 => Set) private sets; 17 | 18 | function addAddressToSet( 19 | bytes32 key, 20 | address addr, 21 | bool maintainList 22 | ) internal 23 | { 24 | Set storage set = sets[key]; 25 | require(set.positions[addr] == 0, "ALREADY_IN_SET"); 26 | 27 | if (maintainList) { 28 | require(set.addresses.length == set.count, "PREVIOUSLY_NOT_MAINTAILED"); 29 | set.addresses.push(addr); 30 | } else { 31 | require(set.addresses.length == 0, "MUST_MAINTAIN"); 32 | } 33 | 34 | set.count += 1; 35 | set.positions[addr] = set.count; 36 | } 37 | 38 | function removeAddressFromSet( 39 | bytes32 key, 40 | address addr 41 | ) 42 | internal 43 | { 44 | Set storage set = sets[key]; 45 | uint pos = set.positions[addr]; 46 | require(pos != 0, "NOT_IN_SET"); 47 | 48 | delete set.positions[addr]; 49 | set.count -= 1; 50 | 51 | if (set.addresses.length > 0) { 52 | address lastAddr = set.addresses[set.count]; 53 | if (lastAddr != addr) { 54 | set.addresses[pos - 1] = lastAddr; 55 | set.positions[lastAddr] = pos; 56 | } 57 | set.addresses.pop(); 58 | } 59 | } 60 | 61 | function removeSet(bytes32 key) 62 | internal 63 | { 64 | delete sets[key]; 65 | } 66 | 67 | function isAddressInSet( 68 | bytes32 key, 69 | address addr 70 | ) 71 | internal 72 | view 73 | returns (bool) 74 | { 75 | return sets[key].positions[addr] != 0; 76 | } 77 | 78 | function numAddressesInSet(bytes32 key) 79 | internal 80 | view 81 | returns (uint) 82 | { 83 | Set storage set = sets[key]; 84 | return set.count; 85 | } 86 | 87 | function addressesInSet(bytes32 key) 88 | internal 89 | view 90 | returns (address[] memory) 91 | { 92 | Set storage set = sets[key]; 93 | require(set.count == set.addresses.length, "NOT_MAINTAINED"); 94 | return sets[key].addresses; 95 | } 96 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/BurnableERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "./ERC20.sol"; 6 | 7 | 8 | /// @title Burnable ERC20 Token Interface 9 | /// @author Brecht Devos - 10 | abstract contract BurnableERC20 is ERC20 11 | { 12 | function burn( 13 | uint value 14 | ) 15 | public 16 | virtual 17 | returns (bool); 18 | 19 | function burnFrom( 20 | address from, 21 | uint value 22 | ) 23 | public 24 | virtual 25 | returns (bool); 26 | } 27 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/Claimable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "./Ownable.sol"; 6 | 7 | 8 | /// @title Claimable 9 | /// @author Brecht Devos - 10 | /// @dev Extension for the Ownable contract, where the ownership needs 11 | /// to be claimed. This allows the new owner to accept the transfer. 12 | contract Claimable is Ownable 13 | { 14 | address public pendingOwner; 15 | 16 | /// @dev Modifier throws if called by any account other than the pendingOwner. 17 | modifier onlyPendingOwner() { 18 | require(msg.sender == pendingOwner, "UNAUTHORIZED"); 19 | _; 20 | } 21 | 22 | /// @dev Allows the current owner to set the pendingOwner address. 23 | /// @param newOwner The address to transfer ownership to. 24 | function transferOwnership( 25 | address newOwner 26 | ) 27 | public 28 | override 29 | onlyOwner 30 | { 31 | require(newOwner != address(0) && newOwner != owner, "INVALID_ADDRESS"); 32 | pendingOwner = newOwner; 33 | } 34 | 35 | /// @dev Allows the pendingOwner address to finalize the transfer. 36 | function claimOwnership() 37 | public 38 | onlyPendingOwner 39 | { 40 | emit OwnershipTransferred(owner, pendingOwner); 41 | owner = pendingOwner; 42 | pendingOwner = address(0); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/Create2.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // Taken from: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/970f687f04d20e01138a3e8ccf9278b1d4b3997b/contracts/utils/Create2.sol 3 | 4 | pragma solidity ^0.7.0; 5 | 6 | /** 7 | * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. 8 | * `CREATE2` can be used to compute in advance the address where a smart 9 | * contract will be deployed, which allows for interesting new mechanisms known 10 | * as 'counterfactual interactions'. 11 | * 12 | * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more 13 | * information. 14 | */ 15 | library Create2 { 16 | /** 17 | * @dev Deploys a contract using `CREATE2`. The address where the contract 18 | * will be deployed can be known in advance via {computeAddress}. Note that 19 | * a contract cannot be deployed twice using the same salt. 20 | */ 21 | function deploy(bytes32 salt, bytes memory bytecode) internal returns (address payable) { 22 | address payable addr; 23 | // solhint-disable-next-line no-inline-assembly 24 | assembly { 25 | addr := create2(0, add(bytecode, 0x20), mload(bytecode), salt) 26 | } 27 | require(addr != address(0), "CREATE2_FAILED"); 28 | return addr; 29 | } 30 | 31 | /** 32 | * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the `bytecode` 33 | * or `salt` will result in a new destination address. 34 | */ 35 | function computeAddress(bytes32 salt, bytes memory bytecode) internal view returns (address) { 36 | return computeAddress(salt, bytecode, address(this)); 37 | } 38 | 39 | /** 40 | * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at 41 | * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. 42 | */ 43 | function computeAddress(bytes32 salt, bytes memory bytecodeHash, address deployer) internal pure returns (address) { 44 | bytes32 bytecodeHashHash = keccak256(bytecodeHash); 45 | bytes32 _data = keccak256( 46 | abi.encodePacked(bytes1(0xff), deployer, salt, bytecodeHashHash) 47 | ); 48 | return address(bytes20(_data << 96)); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/Drainable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "./AddressUtil.sol"; 6 | import "./ERC20.sol"; 7 | import "./ERC20SafeTransfer.sol"; 8 | 9 | 10 | /// @title Drainable 11 | /// @author Brecht Devos - 12 | /// @dev Standard functionality to allow draining funds from a contract. 13 | abstract contract Drainable 14 | { 15 | using AddressUtil for address; 16 | using ERC20SafeTransfer for address; 17 | 18 | event Drained( 19 | address to, 20 | address token, 21 | uint amount 22 | ); 23 | 24 | function drain( 25 | address to, 26 | address token 27 | ) 28 | public 29 | returns (uint amount) 30 | { 31 | require(canDrain(msg.sender, token), "UNAUTHORIZED"); 32 | 33 | if (token == address(0)) { 34 | amount = address(this).balance; 35 | to.sendETHAndVerify(amount, gasleft()); // ETH 36 | } else { 37 | amount = ERC20(token).balanceOf(address(this)); 38 | token.safeTransferAndVerify(to, amount); // ERC20 token 39 | } 40 | 41 | emit Drained(to, token, amount); 42 | } 43 | 44 | // Needs to return if the address is authorized to call drain. 45 | function canDrain(address drainer, address token) 46 | public 47 | virtual 48 | view 49 | returns (bool); 50 | } 51 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/EIP712.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | pragma experimental ABIEncoderV2; 5 | 6 | 7 | library EIP712 8 | { 9 | struct Domain { 10 | string name; 11 | string version; 12 | address verifyingContract; 13 | } 14 | 15 | bytes32 constant internal EIP712_DOMAIN_TYPEHASH = keccak256( 16 | "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" 17 | ); 18 | 19 | string constant internal EIP191_HEADER = "\x19\x01"; 20 | 21 | function hash(Domain memory domain) 22 | internal 23 | pure 24 | returns (bytes32) 25 | { 26 | uint _chainid; 27 | assembly { _chainid := chainid() } 28 | 29 | return keccak256( 30 | abi.encode( 31 | EIP712_DOMAIN_TYPEHASH, 32 | keccak256(bytes(domain.name)), 33 | keccak256(bytes(domain.version)), 34 | _chainid, 35 | domain.verifyingContract 36 | ) 37 | ); 38 | } 39 | 40 | function hashPacked( 41 | bytes32 domainHash, 42 | bytes32 dataHash 43 | ) 44 | internal 45 | pure 46 | returns (bytes32) 47 | { 48 | return keccak256( 49 | abi.encodePacked( 50 | EIP191_HEADER, 51 | domainHash, 52 | dataHash 53 | ) 54 | ); 55 | } 56 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/ERC1271.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | 6 | abstract contract ERC1271 { 7 | // bytes4(keccak256("isValidSignature(bytes32,bytes)") 8 | bytes4 constant internal ERC1271_MAGICVALUE = 0x1626ba7e; 9 | 10 | function isValidSignature( 11 | bytes32 _hash, 12 | bytes memory _signature) 13 | external 14 | view 15 | virtual 16 | returns (bytes4 magicValueB32); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/ERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title ERC20 Token Interface 7 | /// @dev see https://github.com/ethereum/EIPs/issues/20 8 | /// @author Daniel Wang - 9 | abstract contract ERC20 10 | { 11 | function totalSupply() 12 | public 13 | virtual 14 | view 15 | returns (uint); 16 | 17 | function balanceOf( 18 | address who 19 | ) 20 | public 21 | virtual 22 | view 23 | returns (uint); 24 | 25 | function allowance( 26 | address owner, 27 | address spender 28 | ) 29 | public 30 | virtual 31 | view 32 | returns (uint); 33 | 34 | function transfer( 35 | address to, 36 | uint value 37 | ) 38 | public 39 | virtual 40 | returns (bool); 41 | 42 | function transferFrom( 43 | address from, 44 | address to, 45 | uint value 46 | ) 47 | public 48 | virtual 49 | returns (bool); 50 | 51 | function approve( 52 | address spender, 53 | uint value 54 | ) 55 | public 56 | virtual 57 | returns (bool); 58 | } 59 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/ERC2612.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "./ERC20.sol"; 6 | 7 | 8 | /// @title ERC2612 Token with permit – 712-signed approvals but with 9 | /// bytes as signature 10 | /// @dev see https://eips.ethereum.org/EIPS/eip-2612 11 | /// @author Daniel Wang - 12 | abstract contract ERC2612 is ERC20 13 | { 14 | function nonces(address owner) 15 | public 16 | view 17 | virtual 18 | returns (uint); 19 | 20 | function permit( 21 | address owner, 22 | address spender, 23 | uint256 value, 24 | uint256 deadline, 25 | bytes calldata signature 26 | ) 27 | external 28 | virtual; 29 | } 30 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/FloatUtil.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "./MathUint.sol"; 6 | import "../thirdparty/SafeCast.sol"; 7 | 8 | 9 | /// @title Utility Functions for floats 10 | /// @author Brecht Devos - 11 | library FloatUtil 12 | { 13 | using MathUint for uint; 14 | using SafeCast for uint; 15 | 16 | // Decodes a decimal float value that is encoded like `exponent | mantissa`. 17 | // Both exponent and mantissa are in base 10. 18 | // Decoding to an integer is as simple as `mantissa * (10 ** exponent)` 19 | // Will throw when the decoded value overflows an uint96 20 | /// @param f The float value with 5 bits for the exponent 21 | /// @param numBits The total number of bits (numBitsMantissa := numBits - numBitsExponent) 22 | /// @return value The decoded integer value. 23 | function decodeFloat( 24 | uint f, 25 | uint numBits 26 | ) 27 | internal 28 | pure 29 | returns (uint96 value) 30 | { 31 | if (f == 0) { 32 | return 0; 33 | } 34 | uint numBitsMantissa = numBits.sub(5); 35 | uint exponent = f >> numBitsMantissa; 36 | // log2(10**77) = 255.79 < 256 37 | require(exponent <= 77, "EXPONENT_TOO_LARGE"); 38 | uint mantissa = f & ((1 << numBitsMantissa) - 1); 39 | value = mantissa.mul(10 ** exponent).toUint96(); 40 | } 41 | 42 | // Decodes a decimal float value that is encoded like `exponent | mantissa`. 43 | // Both exponent and mantissa are in base 10. 44 | // Decoding to an integer is as simple as `mantissa * (10 ** exponent)` 45 | // Will throw when the decoded value overflows an uint96 46 | /// @param f The float value with 5 bits exponent, 11 bits mantissa 47 | /// @return value The decoded integer value. 48 | function decodeFloat16( 49 | uint16 f 50 | ) 51 | internal 52 | pure 53 | returns (uint96) 54 | { 55 | uint value = ((uint(f) & 2047) * (10 ** (uint(f) >> 11))); 56 | require(value < 2**96, "SafeCast: value doesn\'t fit in 96 bits"); 57 | return uint96(value); 58 | } 59 | 60 | // Decodes a decimal float value that is encoded like `exponent | mantissa`. 61 | // Both exponent and mantissa are in base 10. 62 | // Decoding to an integer is as simple as `mantissa * (10 ** exponent)` 63 | // Will throw when the decoded value overflows an uint96 64 | /// @param f The float value with 5 bits exponent, 19 bits mantissa 65 | /// @return value The decoded integer value. 66 | function decodeFloat24( 67 | uint24 f 68 | ) 69 | internal 70 | pure 71 | returns (uint96) 72 | { 73 | uint value = ((uint(f) & 524287) * (10 ** (uint(f) >> 19))); 74 | require(value < 2**96, "SafeCast: value doesn\'t fit in 96 bits"); 75 | return uint96(value); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/MathUint.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title Utility Functions for uint 7 | /// @author Daniel Wang - 8 | library MathUint 9 | { 10 | using MathUint for uint; 11 | 12 | function mul( 13 | uint a, 14 | uint b 15 | ) 16 | internal 17 | pure 18 | returns (uint c) 19 | { 20 | c = a * b; 21 | require(a == 0 || c / a == b, "MUL_OVERFLOW"); 22 | } 23 | 24 | function sub( 25 | uint a, 26 | uint b 27 | ) 28 | internal 29 | pure 30 | returns (uint) 31 | { 32 | require(b <= a, "SUB_UNDERFLOW"); 33 | return a - b; 34 | } 35 | 36 | function add( 37 | uint a, 38 | uint b 39 | ) 40 | internal 41 | pure 42 | returns (uint c) 43 | { 44 | c = a + b; 45 | require(c >= a, "ADD_OVERFLOW"); 46 | } 47 | 48 | function add64( 49 | uint64 a, 50 | uint64 b 51 | ) 52 | internal 53 | pure 54 | returns (uint64 c) 55 | { 56 | c = a + b; 57 | require(c >= a, "ADD_OVERFLOW"); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/MathUint248.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2022 DeGate DAO 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title Utility Functions for uint 7 | /// @author Daniel Wang - 8 | library MathUint248 9 | { 10 | function add( 11 | uint248 a, 12 | uint248 b 13 | ) 14 | internal 15 | pure 16 | returns (uint248 c) 17 | { 18 | c = a + b; 19 | require(c >= a, "ADD_OVERFLOW"); 20 | } 21 | 22 | function sub( 23 | uint248 a, 24 | uint248 b 25 | ) 26 | internal 27 | pure 28 | returns (uint248 c) 29 | { 30 | require(b <= a, "SUB_UNDERFLOW"); 31 | return a - b; 32 | } 33 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/MathUint96.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title Utility Functions for uint 7 | /// @author Daniel Wang - 8 | library MathUint96 9 | { 10 | function add( 11 | uint96 a, 12 | uint96 b 13 | ) 14 | internal 15 | pure 16 | returns (uint96 c) 17 | { 18 | c = a + b; 19 | require(c >= a, "ADD_OVERFLOW"); 20 | } 21 | 22 | function sub( 23 | uint96 a, 24 | uint96 b 25 | ) 26 | internal 27 | pure 28 | returns (uint96 c) 29 | { 30 | require(b <= a, "SUB_UNDERFLOW"); 31 | return a - b; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/Ownable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title Ownable 7 | /// @author Brecht Devos - 8 | /// @dev The Ownable contract has an owner address, and provides basic 9 | /// authorization control functions, this simplifies the implementation of 10 | /// "user permissions". 11 | contract Ownable 12 | { 13 | address public owner; 14 | 15 | event OwnershipTransferred( 16 | address indexed previousOwner, 17 | address indexed newOwner 18 | ); 19 | 20 | /// @dev The Ownable constructor sets the original `owner` of the contract 21 | /// to the sender. 22 | constructor() 23 | { 24 | owner = msg.sender; 25 | } 26 | 27 | /// @dev Throws if called by any account other than the owner. 28 | modifier onlyOwner() 29 | { 30 | require(msg.sender == owner, "UNAUTHORIZED"); 31 | _; 32 | } 33 | 34 | /// @dev Allows the current owner to transfer control of the contract to a 35 | /// new owner. 36 | /// @param newOwner The address to transfer ownership to. 37 | function transferOwnership( 38 | address newOwner 39 | ) 40 | public 41 | virtual 42 | onlyOwner 43 | { 44 | require(newOwner != address(0), "ZERO_ADDRESS"); 45 | emit OwnershipTransferred(owner, newOwner); 46 | owner = newOwner; 47 | } 48 | 49 | function renounceOwnership() 50 | public 51 | onlyOwner 52 | { 53 | emit OwnershipTransferred(owner, address(0)); 54 | owner = address(0); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/OwnerManagable.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "./AddressSet.sol"; 6 | import "./Claimable.sol"; 7 | 8 | 9 | contract OwnerManagable is Claimable, AddressSet 10 | { 11 | bytes32 internal constant MANAGER = keccak256("__MANAGED__"); 12 | 13 | event ManagerAdded (address indexed manager); 14 | event ManagerRemoved(address indexed manager); 15 | 16 | modifier onlyManager 17 | { 18 | require(isManager(msg.sender), "NOT_MANAGER"); 19 | _; 20 | } 21 | 22 | modifier onlyOwnerOrManager 23 | { 24 | require(msg.sender == owner || isManager(msg.sender), "NOT_OWNER_OR_MANAGER"); 25 | _; 26 | } 27 | 28 | constructor() Claimable() {} 29 | 30 | /// @dev Gets the managers. 31 | /// @return The list of managers. 32 | function managers() 33 | public 34 | view 35 | returns (address[] memory) 36 | { 37 | return addressesInSet(MANAGER); 38 | } 39 | 40 | /// @dev Gets the number of managers. 41 | /// @return The numer of managers. 42 | function numManagers() 43 | public 44 | view 45 | returns (uint) 46 | { 47 | return numAddressesInSet(MANAGER); 48 | } 49 | 50 | /// @dev Checks if an address is a manger. 51 | /// @param addr The address to check. 52 | /// @return True if the address is a manager, False otherwise. 53 | function isManager(address addr) 54 | public 55 | view 56 | returns (bool) 57 | { 58 | return isAddressInSet(MANAGER, addr); 59 | } 60 | 61 | /// @dev Adds a new manager. 62 | /// @param manager The new address to add. 63 | function addManager(address manager) 64 | public 65 | onlyOwner 66 | { 67 | addManagerInternal(manager); 68 | } 69 | 70 | /// @dev Removes a manager. 71 | /// @param manager The manager to remove. 72 | function removeManager(address manager) 73 | public 74 | onlyOwner 75 | { 76 | removeAddressFromSet(MANAGER, manager); 77 | emit ManagerRemoved(manager); 78 | } 79 | 80 | function addManagerInternal(address manager) 81 | internal 82 | { 83 | addAddressToSet(MANAGER, manager, true); 84 | emit ManagerAdded(manager); 85 | } 86 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/ReentrancyGuard.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | 6 | /// @title ReentrancyGuard 7 | /// @author Brecht Devos - 8 | /// @dev Exposes a modifier that guards a function against reentrancy 9 | /// Changing the value of the same storage value multiple times in a transaction 10 | /// is cheap (starting from Istanbul) so there is no need to minimize 11 | /// the number of times the value is changed 12 | contract ReentrancyGuard 13 | { 14 | //The default value must be 0 in order to work behind a proxy. 15 | uint private _guardValue; 16 | 17 | // Use this modifier on a function to prevent reentrancy 18 | modifier nonReentrant() 19 | { 20 | // Check if the guard value has its original value 21 | require(_guardValue == 0, "REENTRANCY"); 22 | 23 | // Set the value to something else 24 | _guardValue = 1; 25 | 26 | // Function body 27 | _; 28 | 29 | // Set the value back 30 | _guardValue = 0; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/lib/SimpleProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../thirdparty/proxies/Proxy.sol"; 6 | 7 | 8 | /// @title SimpleProxy 9 | /// @author Daniel Wang - 10 | contract SimpleProxy is Proxy 11 | { 12 | bytes32 private constant implementationPosition = keccak256( 13 | "org.loopring.protocol.simple.proxy" 14 | ); 15 | 16 | constructor(address _implementation) { 17 | if (_implementation != address(0)) { 18 | setImplementation(_implementation); 19 | } 20 | } 21 | 22 | function setImplementation(address _implementation) 23 | public 24 | { 25 | address _impl = implementation(); 26 | require(_impl == address(0), "INITIALIZED_ALREADY"); 27 | 28 | bytes32 position = implementationPosition; 29 | assembly {sstore(position, _implementation) } 30 | } 31 | 32 | function implementation() 33 | public 34 | override 35 | view 36 | returns (address) 37 | { 38 | address impl; 39 | bytes32 position = implementationPosition; 40 | assembly { impl := sload(position) } 41 | return impl; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/DelayedOwnerContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../aux/access/DelayedOwner.sol"; 6 | import "./DelayedTargetContract.sol"; 7 | 8 | 9 | /// @title DelayedOwnerContract 10 | /// @author Brecht Devos - 11 | contract DelayedOwnerContract is DelayedOwner 12 | { 13 | constructor( 14 | address delayedTargetAddress, 15 | bool setDefaultFunctionDelays 16 | ) 17 | DelayedOwner(delayedTargetAddress, 3 days) 18 | { 19 | if (setDefaultFunctionDelays) { 20 | DelayedTargetContract delayedTarget = DelayedTargetContract(delayedTargetAddress); 21 | setFunctionDelay(delayedTarget.delayedFunctionPayable.selector, 1 days); 22 | setFunctionDelay(delayedTarget.delayedFunctionRevert.selector, 2 days); 23 | setFunctionDelay(delayedTarget.transferOwnership.selector, 3 days); 24 | } 25 | } 26 | 27 | function setFunctionDelayExternal( 28 | address to, 29 | bytes4 functionSelector, 30 | uint delay 31 | ) 32 | external 33 | { 34 | setFunctionDelay(to, functionSelector, delay); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/DelayedTargetContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../lib/Claimable.sol"; 6 | 7 | 8 | /// @title DelayedTargetContract 9 | /// @author Brecht Devos - 10 | contract DelayedTargetContract is Claimable 11 | { 12 | uint public constant MAGIC_VALUE = 0xFEDCBA987654321; 13 | uint public value = 7; 14 | 15 | function delayedFunctionPayable( 16 | uint _value 17 | ) 18 | external 19 | payable 20 | returns (uint) 21 | { 22 | value = _value; 23 | return _value; 24 | } 25 | 26 | function delayedFunctionRevert( 27 | uint _value 28 | ) 29 | external 30 | { 31 | require(false, "DELAYED_REVERT"); 32 | value = _value; 33 | } 34 | 35 | function immediateFunctionPayable( 36 | uint _value 37 | ) 38 | external 39 | payable 40 | { 41 | value = _value; 42 | } 43 | 44 | function immediateFunctionView() 45 | external 46 | pure 47 | returns (uint) 48 | { 49 | return MAGIC_VALUE; 50 | } 51 | 52 | function immediateFunctionRevert( 53 | uint _value 54 | ) 55 | external 56 | payable 57 | { 58 | require(false, "IMMEDIATE_REVERT"); 59 | value = _value; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/DummyToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "./LRCToken.sol"; 6 | 7 | 8 | /// @author Kongliang Zhong - 9 | contract DummyToken is LRCToken { 10 | using SafeMath for uint; 11 | 12 | constructor( 13 | string memory _name, 14 | string memory _symbol, 15 | uint8 _decimals, 16 | uint _totalSupply 17 | ) LRCToken( 18 | _name, 19 | _symbol, 20 | _decimals, 21 | _totalSupply, 22 | msg.sender 23 | ) 24 | { 25 | } 26 | 27 | function setBalance( 28 | address _target, 29 | uint _value 30 | ) 31 | public 32 | { 33 | uint currBalance = balanceOf(_target); 34 | if (_value < currBalance) { 35 | totalSupply_ = totalSupply_.sub(currBalance.sub(_value)); 36 | } else { 37 | totalSupply_ = totalSupply_.add(_value.sub(currBalance)); 38 | } 39 | balances[_target] = _value; 40 | } 41 | 42 | function addBalance( 43 | address _target, 44 | uint _value 45 | ) 46 | public 47 | { 48 | uint currBalance = balanceOf(_target); 49 | require(_value + currBalance >= currBalance, "INVALID_VALUE"); 50 | totalSupply_ = totalSupply_.add(_value); 51 | balances[_target] = currBalance.add(_value); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/LPERC20.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import '../lib/ERC20.sol'; 6 | import '../lib/MathUint.sol'; 7 | 8 | contract LPERC20 is ERC20 { 9 | using MathUint for uint; 10 | 11 | string public constant name = 'Loopring AMM'; 12 | string public constant symbol = 'LLT'; 13 | uint8 public constant decimals = 18; 14 | uint public _totalSupply; 15 | mapping(address => uint) public _balanceOf; 16 | mapping(address => mapping(address => uint)) public _allowance; 17 | 18 | event Approval(address indexed owner, address indexed spender, uint value); 19 | event Transfer(address indexed from, address indexed to, uint value); 20 | 21 | function totalSupply() public virtual view override returns (uint) { 22 | return _totalSupply; 23 | } 24 | 25 | function balanceOf(address owner) public view override virtual returns (uint balance) { 26 | return _balanceOf[owner]; 27 | } 28 | 29 | function allowance(address owner, address spender) public view override returns (uint) { 30 | return _allowance[owner][spender]; 31 | } 32 | 33 | function approve(address spender, uint value) public override returns (bool) { 34 | _approve(msg.sender, spender, value); 35 | return true; 36 | } 37 | 38 | function transfer(address to, uint value) public override returns (bool) { 39 | _transfer(msg.sender, to, value); 40 | return true; 41 | } 42 | 43 | function transferFrom(address from, address to, uint value) public override returns (bool) { 44 | if (_allowance[from][msg.sender] != uint(-1)) { 45 | _allowance[from][msg.sender] = _allowance[from][msg.sender].sub(value); 46 | } 47 | _transfer(from, to, value); 48 | return true; 49 | } 50 | 51 | function _mint(address to, uint value) internal { 52 | _totalSupply = _totalSupply.add(value); 53 | _balanceOf[to] = _balanceOf[to].add(value); 54 | emit Transfer(address(0), to, value); 55 | } 56 | 57 | function _burn(address from, uint value) internal { 58 | _balanceOf[from] = _balanceOf[from].sub(value); 59 | _totalSupply = _totalSupply.sub(value); 60 | emit Transfer(from, address(0), value); 61 | } 62 | 63 | function _approve(address owner, address spender, uint value) private { 64 | _allowance[owner][spender] = value; 65 | emit Approval(owner, spender, value); 66 | } 67 | 68 | function _transfer(address from, address to, uint value) private { 69 | _balanceOf[from] = _balanceOf[from].sub(value); 70 | _balanceOf[to] = _balanceOf[to].add(value); 71 | emit Transfer(from, to, value); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/LzDecompressorContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | 6 | import "../aux/compression/LzDecompressor.sol"; 7 | 8 | contract LzDecompressorContract { 9 | function decompress( 10 | bytes calldata data 11 | ) 12 | external 13 | pure 14 | returns (bytes memory) 15 | { 16 | return LzDecompressor.decompress(data); 17 | } 18 | 19 | function benchmark( 20 | bytes calldata data 21 | ) 22 | external 23 | pure 24 | returns (bytes memory) 25 | { 26 | return LzDecompressor.decompress(data); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/PoseidonContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | 6 | import "../lib/Poseidon.sol"; 7 | import "../core/iface/ExchangeData.sol"; 8 | 9 | 10 | contract PoseidonContract { 11 | function hash_t5f6p52( 12 | uint t0, 13 | uint t1, 14 | uint t2, 15 | uint t3, 16 | uint t4 17 | ) 18 | external 19 | pure 20 | returns (uint) 21 | { 22 | Poseidon.HashInputs5 memory inputs = Poseidon.HashInputs5(t0, t1, t2, t3, t4); 23 | return Poseidon.hash_t5f6p52(inputs, ExchangeData.SNARK_SCALAR_FIELD); 24 | } 25 | 26 | function hash_t6f6p52( 27 | uint t0, 28 | uint t1, 29 | uint t2, 30 | uint t3, 31 | uint t4, 32 | uint t5 33 | ) 34 | external 35 | pure 36 | returns (uint) 37 | { 38 | Poseidon.HashInputs6 memory inputs = Poseidon.HashInputs6(t0, t1, t2, t3, t4, t5); 39 | return Poseidon.hash_t6f6p52(inputs, ExchangeData.SNARK_SCALAR_FIELD); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/TestAccountContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../core/iface/IExchangeV3.sol"; 6 | 7 | import "../lib/AddressUtil.sol"; 8 | import "../lib/MathUint.sol"; 9 | 10 | 11 | contract TestAccountContract { 12 | 13 | using AddressUtil for address payable; 14 | using MathUint for uint; 15 | 16 | IExchangeV3 exchange; 17 | 18 | uint[16] private dummyStorageVariables; 19 | 20 | modifier refund() 21 | { 22 | // Send surplus to msg.sender 23 | uint balanceBefore = address(this).balance.sub(msg.value); 24 | _; 25 | uint balanceAfter = address(this).balance; 26 | msg.sender.sendETHAndVerify(balanceAfter.sub(balanceBefore), gasleft()); 27 | } 28 | 29 | constructor( 30 | address _exchangeAddress 31 | ) 32 | { 33 | exchange = IExchangeV3(_exchangeAddress); 34 | } 35 | 36 | function withdraw( 37 | address token, 38 | uint96 amount, 39 | uint32 accountID 40 | ) 41 | external 42 | payable 43 | refund 44 | { 45 | //exchange.withdraw{value: msg.value}(address(this), token, amount, accountID); 46 | } 47 | 48 | receive() 49 | external 50 | payable 51 | { 52 | // Some expensive operation 53 | for (uint i = 0; i < 16; i++) { 54 | dummyStorageVariables[i] = block.number; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/TransferContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../lib/AddressUtil.sol"; 6 | import "../lib/ERC20SafeTransfer.sol"; 7 | 8 | 9 | contract TransferContract { 10 | 11 | using AddressUtil for address; 12 | using AddressUtil for address payable; 13 | using ERC20SafeTransfer for address; 14 | 15 | uint8 public constant TEST_NOTHING = 0; 16 | uint8 public constant TEST_REQUIRE_FAIL = 1; 17 | uint8 public constant TEST_EXPENSIVE_TRANSFER = 2; 18 | 19 | uint public testCase = TEST_NOTHING; 20 | 21 | uint[16] private dummyStorageVariables; 22 | 23 | function safeTransferWithGasLimit( 24 | address token, 25 | address to, 26 | uint value, 27 | uint gasLimit 28 | ) 29 | external 30 | { 31 | token.safeTransferWithGasLimitAndVerify(to, value, gasLimit); 32 | } 33 | 34 | function safeTransferFromWithGasLimit( 35 | address token, 36 | address from, 37 | address to, 38 | uint value, 39 | uint gasLimit 40 | ) 41 | external 42 | { 43 | token.safeTransferFromWithGasLimitAndVerify(from, to, value, gasLimit); 44 | } 45 | 46 | function sendETH( 47 | address to, 48 | uint amount, 49 | uint gasLimit 50 | ) 51 | external 52 | { 53 | to.sendETHAndVerify(amount, gasLimit); 54 | } 55 | 56 | function setTestCase( 57 | uint8 _testCase 58 | ) 59 | external 60 | { 61 | testCase = _testCase; 62 | } 63 | 64 | receive() 65 | external 66 | payable 67 | { 68 | if (testCase == TEST_NOTHING) { 69 | return; 70 | } else if (testCase == TEST_REQUIRE_FAIL) { 71 | revert("ETH_FAILURE"); 72 | } else if (testCase == TEST_EXPENSIVE_TRANSFER) { 73 | // Some expensive operation 74 | for (uint i = 0; i < 16; i++) { 75 | dummyStorageVariables[i] = block.number; 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/ZeroDecompressorContract.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | // Modified by DeGate DAO, 2022 4 | pragma solidity ^0.7.0; 5 | 6 | import "../aux/compression/ZeroDecompressor.sol"; 7 | 8 | contract ZeroDecompressorContract { 9 | function decompress( 10 | bytes calldata data 11 | ) 12 | external 13 | pure 14 | returns (bytes memory) 15 | { 16 | return ZeroDecompressor.decompress(data, 0); 17 | } 18 | 19 | function benchmark( 20 | bytes calldata data 21 | ) 22 | external 23 | pure 24 | returns (bytes memory) 25 | { 26 | return ZeroDecompressor.decompress(data, 0); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/tokens/GTO.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../DummyToken.sol"; 6 | 7 | contract GTO is DummyToken { 8 | 9 | constructor() DummyToken( 10 | "GTO_TEST", 11 | "GTO", 12 | 18, 13 | 10 ** 27 14 | ) 15 | { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/tokens/INDA.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../DummyToken.sol"; 6 | 7 | contract INDA is DummyToken { 8 | 9 | constructor() DummyToken( 10 | "INDIVISIBLE_A", 11 | "INDA", 12 | 0, 13 | 10 ** 27 14 | ) 15 | { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/tokens/INDB.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../DummyToken.sol"; 6 | 7 | contract INDB is DummyToken { 8 | 9 | constructor() DummyToken( 10 | "INDIVISIBLE_B", 11 | "INDB", 12 | 0, 13 | 10 ** 27 14 | ) 15 | { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/tokens/LRC.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../DummyToken.sol"; 6 | 7 | contract LRC is DummyToken { 8 | 9 | constructor() DummyToken( 10 | "LRC_TEST", 11 | "LRC", 12 | 18, 13 | 10 ** 27 14 | ) 15 | { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/tokens/RDN.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../DummyToken.sol"; 6 | 7 | contract RDN is DummyToken { 8 | 9 | constructor() DummyToken( 10 | "RDN_TEST", 11 | "RDN", 12 | 18, 13 | 10 ** 27 14 | ) 15 | { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/tokens/REP.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../DummyToken.sol"; 6 | 7 | contract REP is DummyToken { 8 | 9 | constructor() DummyToken( 10 | "REP_TEST", 11 | "REP", 12 | 18, 13 | 10 ** 27 14 | ) 15 | { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/test/tokens/WETH.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: Apache-2.0 2 | // Copyright 2017 Loopring Technology Limited. 3 | pragma solidity ^0.7.0; 4 | 5 | import "../DummyToken.sol"; 6 | 7 | contract WETH is DummyToken { 8 | 9 | constructor() DummyToken( 10 | "WETH_TEST", 11 | "WETH", 12 | 18, 13 | 10 ** 27 14 | ) 15 | { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/Cloneable.sol: -------------------------------------------------------------------------------- 1 | 2 | // SPDX-License-Identifier: UNLICENSED 3 | // This code is taken from https://gist.github.com/holiman/069de8d056a531575d2b786df3345665 4 | pragma solidity ^0.7.0; 5 | 6 | library Cloneable { 7 | function clone(address a) 8 | external 9 | returns (address) 10 | { 11 | 12 | /* 13 | Assembly of the code that we want to use as init-code in the new contract, 14 | along with stack values: 15 | # bottom [ STACK ] top 16 | PUSH1 00 # [ 0 ] 17 | DUP1 # [ 0, 0 ] 18 | PUSH20 19 |
# [0,0, address] 20 | DUP1 # [0,0, address ,address] 21 | EXTCODESIZE # [0,0, address, size ] 22 | DUP1 # [0,0, address, size, size] 23 | SWAP4 # [ size, 0, address, size, 0] 24 | DUP1 # [ size, 0, address ,size, 0,0] 25 | SWAP2 # [ size, 0, address, 0, 0, size] 26 | SWAP3 # [ size, 0, size, 0, 0, address] 27 | EXTCODECOPY # [ size, 0] 28 | RETURN 29 | 30 | The code above weighs in at 33 bytes, which is _just_ above fitting into a uint. 31 | So a modified version is used, where the initial PUSH1 00 is replaced by `PC`. 32 | This is one byte smaller, and also a bit cheaper Wbase instead of Wverylow. It only costs 2 gas. 33 | 34 | PC # [ 0 ] 35 | DUP1 # [ 0, 0 ] 36 | PUSH20 37 |
# [0,0, address] 38 | DUP1 # [0,0, address ,address] 39 | EXTCODESIZE # [0,0, address, size ] 40 | DUP1 # [0,0, address, size, size] 41 | SWAP4 # [ size, 0, address, size, 0] 42 | DUP1 # [ size, 0, address ,size, 0,0] 43 | SWAP2 # [ size, 0, address, 0, 0, size] 44 | SWAP3 # [ size, 0, size, 0, 0, address] 45 | EXTCODECOPY # [ size, 0] 46 | RETURN 47 | 48 | The opcodes are: 49 | 58 80 73
80 3b 80 93 80 91 92 3c F3 50 | We get
in there by OR:ing the upshifted address into the 0-filled space. 51 | 5880730000000000000000000000000000000000000000803b80938091923cF3 52 | +000000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx000000000000000000 53 | ----------------------------------------------------------------- 54 | 588073xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00000803b80938091923cF3 55 | 56 | This is simply stored at memory position 0, and create is invoked. 57 | */ 58 | address retval; 59 | assembly{ 60 | mstore(0x0, or (0x5880730000000000000000000000000000000000000000803b80938091923cF3 ,mul(a,0x1000000000000000000))) 61 | retval := create(0,0, 32) 62 | } 63 | return retval; 64 | } 65 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/chainlink/AggregatorInterface.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | pragma solidity ^0.7.0; 3 | 4 | interface AggregatorInterface { 5 | function latestAnswer() external view returns (int256); 6 | function latestTimestamp() external view returns (uint256); 7 | function latestRound() external view returns (uint256); 8 | function getAnswer(uint256 roundId) external view returns (int256); 9 | function getTimestamp(uint256 roundId) external view returns (uint256); 10 | 11 | event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp); 12 | event NewRound(uint256 indexed roundId, address indexed startedBy); 13 | } 14 | -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/chi/IChiToken.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | 3 | pragma solidity ^0.7.0; 4 | 5 | import "../../lib/ERC20.sol"; 6 | 7 | 8 | abstract contract IChiToken is ERC20 9 | { 10 | function free(uint256 value) 11 | external 12 | virtual 13 | returns (uint256); 14 | 15 | function freeUpTo(uint256 value) 16 | external 17 | virtual 18 | returns (uint256); 19 | 20 | function freeFrom(address from, uint256 value) 21 | external 22 | virtual 23 | returns (uint256); 24 | 25 | function freeFromUpTo(address from, uint256 value) 26 | external 27 | virtual 28 | returns (uint256 freed); 29 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/opengsn2/BaseRelayRecipient.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier:MIT 2 | pragma solidity ^0.7.0; 3 | 4 | import "./IRelayRecipient.sol"; 5 | 6 | /** 7 | * A base contract to be inherited by any contract that want to receive relayed transactions 8 | * A subclass must use "_msgSender()" instead of "msg.sender" 9 | */ 10 | abstract contract BaseRelayRecipient is IRelayRecipient { 11 | 12 | /* 13 | * Forwarder singleton we accept calls from 14 | */ 15 | address public immutable trustedForwarder; 16 | 17 | constructor(address _forwarder) 18 | { 19 | trustedForwarder = _forwarder; 20 | } 21 | 22 | /* 23 | * require a function to be called through GSN only 24 | */ 25 | modifier trustedForwarderOnly() { 26 | require(msg.sender == address(trustedForwarder), "Function can only be called through the trusted Forwarder"); 27 | _; 28 | } 29 | 30 | function isTrustedForwarder(address forwarder) public override view returns(bool) { 31 | return forwarder == trustedForwarder; 32 | } 33 | 34 | /** 35 | * return the sender of this call. 36 | * if the call came through our trusted forwarder, return the original sender. 37 | * otherwise, return `msg.sender`. 38 | * should be used in the contract anywhere instead of msg.sender 39 | */ 40 | function _msgSender() internal override virtual view returns (address payable ret) { 41 | if (msg.data.length >= 24 && isTrustedForwarder(msg.sender)) { 42 | // At this point we know that the sender is a trusted forwarder, 43 | // so we trust that the last bytes of msg.data are the verified sender address. 44 | // extract sender address from the end of msg.data 45 | assembly { 46 | ret := shr(96,calldataload(sub(calldatasize(),20))) 47 | } 48 | } else { 49 | return msg.sender; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/opengsn2/IKnowForwarderAddress.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier:MIT 2 | pragma solidity ^0.7.0; 3 | 4 | interface IKnowForwarderAddress { 5 | 6 | /** 7 | * return the forwarder we trust to forward relayed transactions to us. 8 | * the forwarder is required to verify the sender's signature, and verify 9 | * the call is not a replay. 10 | */ 11 | function getTrustedForwarder() external view returns(address); 12 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/opengsn2/IRelayRecipient.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier:MIT 2 | pragma solidity ^0.7.0; 3 | 4 | /** 5 | * a contract must implement this interface in order to support relayed transaction. 6 | * It is better to inherit the BaseRelayRecipient as its implementation. 7 | */ 8 | abstract contract IRelayRecipient { 9 | 10 | /** 11 | * return if the forwarder is trusted to forward relayed transactions to us. 12 | * the forwarder is required to verify the sender's signature, and verify 13 | * the call is not a replay. 14 | */ 15 | function isTrustedForwarder(address forwarder) public virtual view returns(bool); 16 | 17 | /** 18 | * return the sender of this call. 19 | * if the call came through our trusted forwarder, then the real sender is appended as the last 20 bytes 20 | * of the msg.data. 21 | * otherwise, return `msg.sender` 22 | * should be used in the contract anywhere instead of msg.sender 23 | */ 24 | function _msgSender() internal virtual view returns (address payable); 25 | 26 | function versionRecipient() external virtual view returns (string memory); 27 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/proxies/OwnedUpgradabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // This code is taken from https://github.com/OpenZeppelin/openzeppelin-labs 3 | // with minor modifications. 4 | pragma solidity ^0.7.0; 5 | 6 | import './UpgradabilityProxy.sol'; 7 | 8 | 9 | /** 10 | * @title OwnedUpgradabilityProxy 11 | * @dev This contract combines an upgradeability proxy with basic authorization control functionalities 12 | */ 13 | contract OwnedUpgradabilityProxy is UpgradeabilityProxy { 14 | /** 15 | * @dev Event to show ownership has been transferred 16 | * @param previousOwner representing the address of the previous owner 17 | * @param newOwner representing the address of the new owner 18 | */ 19 | event ProxyOwnershipTransferred(address previousOwner, address newOwner); 20 | 21 | // Storage position of the owner of the contract 22 | bytes32 private constant proxyOwnerPosition = keccak256("org.zeppelinos.proxy.owner"); 23 | 24 | /** 25 | * @dev the constructor sets the original owner of the contract to the sender account. 26 | */ 27 | constructor() { 28 | setUpgradabilityOwner(msg.sender); 29 | } 30 | 31 | /** 32 | * @dev Throws if called by any account other than the owner. 33 | */ 34 | modifier onlyProxyOwner() { 35 | require(msg.sender == proxyOwner()); 36 | _; 37 | } 38 | 39 | /** 40 | * @dev Tells the address of the owner 41 | * @return owner the address of the owner 42 | */ 43 | function proxyOwner() public view returns (address owner) { 44 | bytes32 position = proxyOwnerPosition; 45 | assembly { 46 | owner := sload(position) 47 | } 48 | } 49 | 50 | /** 51 | * @dev Sets the address of the owner 52 | */ 53 | function setUpgradabilityOwner(address newProxyOwner) internal { 54 | bytes32 position = proxyOwnerPosition; 55 | assembly { 56 | sstore(position, newProxyOwner) 57 | } 58 | } 59 | 60 | /** 61 | * @dev Allows the current owner to transfer control of the contract to a newOwner. 62 | * @param newOwner The address to transfer ownership to. 63 | */ 64 | function transferProxyOwnership(address newOwner) public onlyProxyOwner { 65 | require(newOwner != address(0)); 66 | emit ProxyOwnershipTransferred(proxyOwner(), newOwner); 67 | setUpgradabilityOwner(newOwner); 68 | } 69 | 70 | /** 71 | * @dev Allows the proxy owner to upgrade the current version of the proxy. 72 | * @param implementation representing the address of the new implementation to be set. 73 | */ 74 | function upgradeTo(address implementation) public onlyProxyOwner { 75 | _upgradeTo(implementation); 76 | } 77 | 78 | /** 79 | * @dev Allows the proxy owner to upgrade the current version of the proxy and call the new implementation 80 | * to initialize whatever is needed through a low level call. 81 | * @param implementation representing the address of the new implementation to be set. 82 | * @param data represents the msg.data to bet sent in the low level call. This parameter may include the function 83 | * signature of the implementation to be called with the needed payload 84 | */ 85 | function upgradeToAndCall(address implementation, bytes memory data) payable public onlyProxyOwner { 86 | upgradeTo(implementation); 87 | (bool success, ) = address(this).call{value: msg.value}(data); 88 | require(success); 89 | } 90 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/proxies/Proxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // This code is taken from https://github.com/OpenZeppelin/openzeppelin-labs 3 | // with minor modifications. 4 | pragma solidity ^0.7.0; 5 | 6 | /** 7 | * @title Proxy 8 | * @dev Gives the possibility to delegate any call to a foreign implementation. 9 | */ 10 | abstract contract Proxy { 11 | /** 12 | * @dev Tells the address of the implementation where every call will be delegated. 13 | * @return impl address of the implementation to which it will be delegated 14 | */ 15 | function implementation() public view virtual returns (address impl); 16 | 17 | receive() payable external { 18 | _fallback(); 19 | } 20 | 21 | fallback() payable external { 22 | _fallback(); 23 | } 24 | 25 | function _fallback() private { 26 | address _impl = implementation(); 27 | require(_impl != address(0)); 28 | 29 | assembly { 30 | let ptr := mload(0x40) 31 | calldatacopy(ptr, 0, calldatasize()) 32 | let result := delegatecall(gas(), _impl, ptr, calldatasize(), 0, 0) 33 | let size := returndatasize() 34 | returndatacopy(ptr, 0, size) 35 | 36 | switch result 37 | case 0 { revert(ptr, size) } 38 | default { return(ptr, size) } 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /packages/loopring_v3/contracts/thirdparty/proxies/UpgradabilityProxy.sol: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: UNLICENSED 2 | // This code is taken from https://github.com/OpenZeppelin/openzeppelin-labs 3 | // with minor modifications. 4 | pragma solidity ^0.7.0; 5 | 6 | import './Proxy.sol'; 7 | 8 | 9 | /** 10 | * @title UpgradeabilityProxy 11 | * @dev This contract represents a proxy where the implementation address to which it will delegate can be upgraded 12 | */ 13 | contract UpgradeabilityProxy is Proxy { 14 | /** 15 | * @dev This event will be emitted every time the implementation gets upgraded 16 | * @param implementation representing the address of the upgraded implementation 17 | */ 18 | event Upgraded(address indexed implementation); 19 | 20 | // Storage position of the address of the current implementation 21 | bytes32 private constant implementationPosition = keccak256("org.zeppelinos.proxy.implementation"); 22 | 23 | /** 24 | * @dev Constructor function 25 | */ 26 | constructor() {} 27 | 28 | /** 29 | * @dev Tells the address of the current implementation 30 | * @return impl address of the current implementation 31 | */ 32 | function implementation() public view override returns (address impl) { 33 | bytes32 position = implementationPosition; 34 | assembly { 35 | impl := sload(position) 36 | } 37 | } 38 | 39 | /** 40 | * @dev Sets the address of the current implementation 41 | * @param newImplementation address representing the new implementation to be set 42 | */ 43 | function setImplementation(address newImplementation) internal { 44 | bytes32 position = implementationPosition; 45 | assembly { 46 | sstore(position, newImplementation) 47 | } 48 | } 49 | 50 | /** 51 | * @dev Upgrades the implementation address 52 | * @param newImplementation representing the address of the new implementation to be set 53 | */ 54 | function _upgradeTo(address newImplementation) internal { 55 | address currentImplementation = implementation(); 56 | require(currentImplementation != newImplementation); 57 | setImplementation(newImplementation); 58 | emit Upgraded(newImplementation); 59 | } 60 | } -------------------------------------------------------------------------------- /packages/loopring_v3/deploy-contract-install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git submodule update --init --recursive 4 | 5 | case "$OSTYPE" in 6 | linux*) 7 | echo "OS: Linux" 8 | cd ethsnarks 9 | sudo apt-get update 10 | sudo apt-get -y install make 11 | sudo make ubuntu-dependencies 12 | curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash 13 | export NVM_DIR="$HOME/.nvm" 14 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 15 | nvm install 10 16 | ;; 17 | 18 | *) 19 | echo "unsupported OS: $OSTYPE" 20 | exit 0 21 | ;; 22 | esac 23 | 24 | make PIP_ARGS= python-dependencies 25 | cd .. 26 | npm install 27 | -------------------------------------------------------------------------------- /packages/loopring_v3/deployment/flatten-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$#" -ne 1 ] || ! [ -d "$1" ]; then 4 | echo "Usage: $0 DIRECTORY" >&2 5 | exit 1 6 | fi 7 | 8 | DEST="$1/flattened" 9 | 10 | FLATTER_COMMAND="../node_modules/.bin/truffle-flattener" 11 | 12 | SPDX_FILTER="SPDX-License-Identifier" 13 | SPDX_LINE="// SPDX-License-Identifier: Apache-2.0" 14 | PRAGMA_SOL_FILTER="pragma solidity" 15 | PRAGMA_SOL_LINE="pragma solidity ^0.7.0;" 16 | PRAGMA_EXPR_FILTER="pragma experimental" 17 | PRAGMA_EXPR_LINE="pragma experimental ABIEncoderV2;" 18 | 19 | declare -a all_contracts=( 20 | "contracts/core/impl/ExchangeV3.sol" 21 | "contracts/core/impl/libexchange/ExchangeBalances.sol" 22 | "contracts/core/impl/libexchange/ExchangeTokens.sol" 23 | "contracts/core/impl/libexchange/ExchangeWithdrawals.sol" 24 | "contracts/core/impl/libexchange/ExchangeAdmins.sol" 25 | "contracts/core/impl/libexchange/ExchangeDeposits.sol" 26 | "contracts/core/impl/libexchange/ExchangeGenesis.sol" 27 | "contracts/core/impl/libexchange/ExchangeBlocks.sol" 28 | ) 29 | 30 | mkdir -p $DEST 31 | 32 | for contract in "${all_contracts[@]}" 33 | do 34 | file_name=`basename $contract .sol` 35 | echo "flattening ${contract} ..." 36 | dest_file="$DEST/${file_name}_flat.sol" 37 | $FLATTER_COMMAND "../$contract" \ 38 | | grep -v "$SPDX_FILTER" \ 39 | | grep -v "$PRAGMA_SOL_FILTER" > $dest_file 40 | 41 | headers="$SPDX_LINE\n$PRAGMA_SOL_LINE" 42 | if grep -q "$PRAGMA_EXPR_FILTER" $dest_file; then 43 | headers="$headers\n$PRAGMA_EXPR_LINE" 44 | cat $dest_file | grep -v "$PRAGMA_EXPR_FILTER" > "${dest_file}.tmp0" && mv "${dest_file}.tmp0" $dest_file 45 | fi 46 | 47 | (echo -e "$headers" && cat $dest_file ) > "${dest_file}.tmp" && mv "${dest_file}.tmp" $dest_file 48 | 49 | echo "${file_name}.sol successfully flattened, saved to ${dest_file}" 50 | done 51 | -------------------------------------------------------------------------------- /packages/loopring_v3/docker/.gitignore: -------------------------------------------------------------------------------- 1 | contracts*.txt 2 | -------------------------------------------------------------------------------- /packages/loopring_v3/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mhart/alpine-node:10.15.3 2 | 3 | RUN mkdir -p /usr/local/loopring3 4 | WORKDIR /usr/local/loopring3 5 | 6 | RUN mkdir testdata 7 | 8 | RUN npm install -g ganache-cli@6.4.3 9 | 10 | ADD docker_ganache.sh docker_ganache.sh 11 | 12 | RUN chmod +x docker_ganache.sh 13 | 14 | EXPOSE 8545 15 | 16 | CMD sh docker_ganache.sh 17 | -------------------------------------------------------------------------------- /packages/loopring_v3/docker/build_image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | target_image=contracts-beta2:0.1 4 | container_name=contracts_beta2_1 5 | 6 | docker rmi $target_image 7 | 8 | docker build -t $target_image . 9 | 10 | container_id_old=$(docker ps -aqf "name=$container_name") 11 | echo "container_id_old: $container_id_old" 12 | if [ ! -z "$container_id_old" ]; then 13 | docker rm $container_id_old 14 | fi 15 | 16 | docker run --name $container_name -p 8545:8545 $target_image & 17 | 18 | sleep 3 19 | 20 | docker_id=$(docker ps -qf "name=$container_name") 21 | echo "docker_id: $docker_id" 22 | 23 | if [ -z "$docker_id" ]; then 24 | echo "docker id is empty, docker run failed." 25 | exit 1 26 | fi 27 | 28 | cd .. 29 | 30 | npm run migrate > "docker/$container_name.txt" 31 | 32 | docker commit $docker_id $target_image 33 | 34 | docker kill $docker_id 35 | 36 | echo "docker image: $target_image build succeeded!" 37 | -------------------------------------------------------------------------------- /packages/loopring_v3/genAbi.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const contractBuildPath = "./build/contracts"; 3 | const abiDir = "./ABI/version36"; 4 | 5 | fs.readdir(contractBuildPath, function(err, files) { 6 | if (err) { 7 | return console.log( 8 | `Unable to scan directory: ${contractBuildPath}, error: ${err}` 9 | ); 10 | } 11 | 12 | files.forEach(function(file) { 13 | const contract = JSON.parse( 14 | fs.readFileSync(contractBuildPath + "/" + file), 15 | "utf8" 16 | ); 17 | const abiStr = JSON.stringify(contract.abi); 18 | // abiFile: same as file but replace ext .json with .abi 19 | const abiFile = abiDir + "/" + file.slice(0, -4) + "abi"; 20 | fs.writeFileSync(abiFile, abiStr); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/loopring_v3/genAbi.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf ABI/* 4 | 5 | node_modules/solc/solcjs \ 6 | -o ABI/version36/ --overwrite \ 7 | --abi contracts/core/iface/*.sol \ 8 | --allow-paths contracts/thirdparty/proxies/*.sol contracts/thirdparty/*.sol contracts/lib/*.sol 9 | 10 | ABI_PATH="ABI/version36" 11 | 12 | for file in $ABI_PATH/* 13 | do 14 | rename_file=$(echo $file | awk '{n=split($0,a,"_"); print a[n]}') 15 | mv $file $ABI_PATH/$rename_file 16 | done 17 | -------------------------------------------------------------------------------- /packages/loopring_v3/globals.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'bn.js' { 2 | import { Buffer } from 'buffer' 3 | 4 | type Endianness = 'le'|'be' 5 | 6 | class BN { 7 | constructor(number: number|string|number[]|Buffer, base?: number, endian?: Endianness) 8 | clone(): BN 9 | toString(base?: number, length?: number): string 10 | toNumber(): number 11 | toJSON(): string 12 | toArray(endian?: Endianness, length?: number): number[] 13 | toBuffer(endian?: Endianness, length?: number): Buffer 14 | bitLength(): number 15 | zeroBits(): number 16 | byteLength(): number 17 | isNeg(): boolean 18 | isEven(): boolean 19 | isOdd(): boolean 20 | isZero(): boolean 21 | cmp(b: any): number 22 | lt(b: any): boolean 23 | lte(b: any): boolean 24 | gt(b: any): boolean 25 | gte(b: any): boolean 26 | eq(b: any): boolean 27 | isBN(b: any): boolean 28 | 29 | neg(): BN 30 | abs(): BN 31 | add(b: BN): BN 32 | sub(b: BN): BN 33 | mul(b: BN): BN 34 | sqr(): BN 35 | pow(b: BN): BN 36 | div(b: BN): BN 37 | mod(b: BN): BN 38 | divRound(b: BN): BN 39 | 40 | or(b: BN): BN 41 | and(b: BN): BN 42 | xor(b: BN): BN 43 | setn(b: number): BN 44 | shln(b: number): BN 45 | shrn(b: number): BN 46 | testn(b: number): boolean 47 | maskn(b: number): BN 48 | bincn(b: number): BN 49 | notn(w: number): BN 50 | 51 | gcd(b: BN): BN 52 | egcd(b: BN): { a: BN, b: BN, gcd: BN } 53 | invm(b: BN): BN 54 | 55 | iadd(b: BN): BN 56 | isub(b: BN): BN 57 | } 58 | export = BN 59 | } 60 | 61 | declare module "ethereumjs-abi"; 62 | declare module "ethereumjs-util"; 63 | declare module "es6-promisify"; 64 | declare module "sha2"; 65 | 66 | // declare module 'protocol-simulator-core'; 67 | 68 | // Truffle injects the following into the global scope 69 | declare var web3: any; 70 | declare var artifacts: any; 71 | declare var contract: any; 72 | declare var assert: any; 73 | -------------------------------------------------------------------------------- /packages/loopring_v3/install: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | git submodule update --init --recursive 4 | 5 | case "$OSTYPE" in 6 | darwin*) 7 | echo "OS: MacOS" 8 | brew install nvm 9 | NVM_DIR="$HOME/.nvm" 10 | [ -s "/usr/local/opt/nvm/nvm.sh" ] && . "/usr/local/opt/nvm/nvm.sh" # This loads nvm 11 | cd ethsnarks 12 | make mac-dependencies 13 | nvm install --lts 14 | ;; 15 | 16 | linux*) 17 | echo "OS: Linux" 18 | cd ethsnarks 19 | sudo apt-get update 20 | sudo apt-get -y install make 21 | sudo make ubuntu-dependencies 22 | curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash 23 | export NVM_DIR="$HOME/.nvm" 24 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm 25 | nvm install --lts 26 | ;; 27 | 28 | *) 29 | echo "unsupported OS: $OSTYPE" 30 | exit 0 31 | ;; 32 | esac 33 | 34 | make PIP_ARGS= python-dependencies 35 | cd .. 36 | npm install 37 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/21_grantAccessSubmitblock.js: -------------------------------------------------------------------------------- 1 | // Deploy the ExchangeV3 library which is very large in terms of 2 | // gas usage. We need to deploy most libraries linked from it as stand-alone 3 | // libraries, otherwise we'll run into the 'exceeded block gas limit' issue. 4 | 5 | const fs = require("fs"); 6 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 7 | 8 | module.exports = function(deployer, network, accounts) { 9 | deployer.then(async () => { 10 | console.log("LoopringIOExchangeOwner grantAccess:"); 11 | 12 | const ownerContract = await LoopringIOExchangeOwner.deployed(); 13 | const selector = "0x53228430"; // submitBlocks 14 | 15 | const postmanAddress = "0xD587a78e828Fd312282E076b602141951F92829c"; 16 | 17 | let ret = await ownerContract.grantAccess(postmanAddress, selector, true); 18 | console.log(ret); 19 | }); 20 | }; 21 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/22_registerCircuit.js: -------------------------------------------------------------------------------- 1 | // Deploy the ExchangeV3 library which is very large in terms of 2 | // gas usage. We need to deploy most libraries linked from it as stand-alone 3 | // libraries, otherwise we'll run into the 'exceeded block gas limit' issue. 4 | 5 | const fs = require("fs"); 6 | const BlockVerifier = artifacts.require("BlockVerifier"); 7 | 8 | module.exports = function(deployer, network, accounts) { 9 | function flattenList(l) { 10 | return [].concat.apply([], l); 11 | } 12 | 13 | function flattenVK(vk) { 14 | return [ 15 | flattenList([vk.alpha[0], vk.alpha[1], flattenList(vk.beta), flattenList(vk.gamma), flattenList(vk.delta)]), 16 | flattenList(vk.gammaABC) 17 | ]; 18 | } 19 | 20 | deployer.then(async () => { 21 | // set VK in blockVerifier 22 | const vk = JSON.parse(fs.readFileSync("test/all_2_vk_testb.json", "ascii")); 23 | const vkFlattened = flattenList(flattenVK(vk)); 24 | const blockVerifier = await BlockVerifier.deployed(); 25 | 26 | console.log(accounts[0]); 27 | console.log("blockVerifier", blockVerifier.address); 28 | console.log("vkFlattened", vkFlattened); 29 | 30 | ret = await blockVerifier.registerCircuit(0, 2, 0, vkFlattened); 31 | 32 | console.log(ret); 33 | }); 34 | }; 35 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/23_reDeploy_BlockVerifier.js: -------------------------------------------------------------------------------- 1 | // Deploy all auxiliary contracts used by either Exchange, LoopringV3, 2 | // or UniversalRegistry. 3 | 4 | const ProtocolFeeVault = artifacts.require("ProtocolFeeVault"); 5 | const BatchVerifier = artifacts.require("BatchVerifier"); 6 | const BlockVerifier = artifacts.require("BlockVerifier"); 7 | const ExchangeV3 = artifacts.require("./impl/ExchangeV3.sol"); 8 | const LoopringV3 = artifacts.require("LoopringV3"); 9 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 10 | 11 | module.exports = function(deployer, network, accounts) { 12 | deployer.then(async () => { 13 | console.log("BlockVerifier.address old", BlockVerifier.address); 14 | 15 | // 1. deploy new BlockVerifier 16 | await deployer.link(BatchVerifier, BlockVerifier); 17 | await deployer.deploy(BlockVerifier); 18 | 19 | console.log("BlockVerifier.address new", BlockVerifier.address); 20 | 21 | // 2. refreshBlockVerifier 22 | const ownerContract = await LoopringIOExchangeOwner.deployed(); 23 | const exchangeV3 = await ExchangeV3.deployed(); 24 | const refreshData = exchangeV3.contract.methods.refreshBlockVerifier(BlockVerifier.address).encodeABI(); 25 | console.log("refreshData:", refreshData); 26 | await ownerContract.transact(refreshData); 27 | }); 28 | }; 29 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/24_registerToken.js: -------------------------------------------------------------------------------- 1 | // Deploy all auxiliary contracts used by either Exchange, LoopringV3, 2 | // or UniversalRegistry. 3 | 4 | const ProtocolFeeVault = artifacts.require("ProtocolFeeVault"); 5 | const BatchVerifier = artifacts.require("BatchVerifier"); 6 | const BlockVerifier = artifacts.require("BlockVerifier"); 7 | const ExchangeV3 = artifacts.require("./impl/ExchangeV3.sol"); 8 | const LoopringV3 = artifacts.require("LoopringV3"); 9 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 10 | 11 | module.exports = function(deployer, network, accounts) { 12 | deployer.then(async () => { 13 | const ownerContract = await LoopringIOExchangeOwner.deployed(); 14 | const exchangeV3 = await ExchangeV3.deployed(); 15 | 16 | const tokenAddress = "0x351be5fde823e1d3ecc8b13645e649663bc07b13"; // test token 17 | 18 | const transactData = exchangeV3.contract.methods.registerToken(tokenAddress).encodeABI(); 19 | console.log("transactData:", transactData); 20 | await ownerContract.transact(transactData); 21 | 22 | const tokenId = await exchangeV3.getTokenID(tokenAddress); 23 | console.log("tokenId", tokenId.toString(10)); 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/27_setDepositParams.js: -------------------------------------------------------------------------------- 1 | // Deploy all auxiliary contracts used by either Exchange, LoopringV3, 2 | // or UniversalRegistry. 3 | 4 | const ProtocolFeeVault = artifacts.require("ProtocolFeeVault"); 5 | const BatchVerifier = artifacts.require("BatchVerifier"); 6 | const BlockVerifier = artifacts.require("BlockVerifier"); 7 | const ExchangeV3 = artifacts.require("./impl/ExchangeV3.sol"); 8 | const LoopringV3 = artifacts.require("LoopringV3"); 9 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 10 | 11 | module.exports = function(deployer, network, accounts) { 12 | deployer.then(async () => { 13 | const ownerContract = await LoopringIOExchangeOwner.deployed(); 14 | const exchangeV3 = await ExchangeV3.deployed(); 15 | 16 | console.log("ownerContract", ownerContract.address); 17 | console.log("exchangeV3", exchangeV3.address); 18 | 19 | const freeDepositMax = 5000; 20 | const freeDepositRemained = 5000; 21 | const freeSlotPerBlock = 2; 22 | const depositFee = "10000000000000000"; 23 | 24 | const transactData = exchangeV3.contract.methods 25 | .setDepositParams(freeDepositMax, freeDepositRemained, freeSlotPerBlock, depositFee) 26 | .encodeABI(); 27 | console.log("transactData:", transactData); 28 | await ownerContract.transact(transactData); 29 | 30 | const freeDepositSlot = await exchangeV3.getFreeDepositRemained(); 31 | console.log("freeDepositSlot", freeDepositSlot.toString(10)); 32 | }); 33 | }; 34 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/28_getExchangeData.js: -------------------------------------------------------------------------------- 1 | // Deploy the ExchangeV3 library which is very large in terms of 2 | // gas usage. We need to deploy most libraries linked from it as stand-alone 3 | // libraries, otherwise we'll run into the 'exceeded block gas limit' issue. 4 | 5 | const fs = require("fs"); 6 | const ExchangeV3 = artifacts.require("./impl/ExchangeV3.sol"); 7 | const LoopringV3 = artifacts.require("LoopringV3"); 8 | const DefaultDepositContract = artifacts.require("DefaultDepositContract"); 9 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 10 | const BlockVerifier = artifacts.require("BlockVerifier"); 11 | 12 | module.exports = function(deployer, network, accounts) { 13 | deployer.then(async () => { 14 | const loopringV3 = await LoopringV3.deployed(); 15 | 16 | let lv1 = await loopringV3.forcedWithdrawalFee(); 17 | console.log("loopringV3.address", loopringV3.address); 18 | console.log("loopringV3.forcedWithdrawalFee old", lv1.toString(10)); 19 | 20 | const exchangeV3 = await ExchangeV3.deployed(); 21 | // let ePFv = await exchangeV3.getProtocolFeeValues(); 22 | console.log("exchangeV3.address", exchangeV3.address); 23 | // console.log("exchangeV3.getProtocolFeeValues", ePFv.protocolFeeBips.toString(10)); 24 | // console.log("exchangeV3.getProtocolFeeValues", ePFv.previousProtocolFeeBips.toString(10)); 25 | 26 | let owner = "0x6871979c76a1313949b2E928F75dC316E02bfe33"; 27 | let token = "0x0000000000000000000000000000000000000000"; 28 | let amount = await exchangeV3.getPendingDepositAmount(owner, token); 29 | 30 | console.log("amount", amount.toString(10)); 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/29_updateForceWithdrawFee.js: -------------------------------------------------------------------------------- 1 | // Deploy all auxiliary contracts used by either Exchange, LoopringV3, 2 | // or UniversalRegistry. 3 | 4 | const ProtocolFeeVault = artifacts.require("ProtocolFeeVault"); 5 | const BatchVerifier = artifacts.require("BatchVerifier"); 6 | const BlockVerifier = artifacts.require("BlockVerifier"); 7 | const ExchangeV3 = artifacts.require("./impl/ExchangeV3.sol"); 8 | const LoopringV3 = artifacts.require("LoopringV3"); 9 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 10 | 11 | module.exports = function(deployer, network, accounts) { 12 | deployer.then(async () => { 13 | const loopringV3 = await LoopringV3.deployed(); 14 | 15 | const protocolFeeVault = await loopringV3.protocolFeeVault(); 16 | 17 | console.log("loopringV3 ", loopringV3.address); 18 | console.log("protocolFeeVault ", protocolFeeVault); 19 | 20 | const forceWithdrawFee = "10000000000000000"; // 0.01 eth 21 | await loopringV3.updateSettings(protocolFeeVault, forceWithdrawFee); 22 | }); 23 | }; 24 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations-scripts/30_updateProtocolFeeSettings_delay.js: -------------------------------------------------------------------------------- 1 | // Deploy the ExchangeV3 library which is very large in terms of 2 | // gas usage. We need to deploy most libraries linked from it as stand-alone 3 | // libraries, otherwise we'll run into the 'exceeded block gas limit' issue. 4 | 5 | const fs = require("fs"); 6 | const ExchangeAdmins = artifacts.require("ExchangeAdmins"); 7 | const ExchangeBalances = artifacts.require("ExchangeBalances"); 8 | const ExchangeBlocks = artifacts.require("ExchangeBlocks"); 9 | const ExchangeDeposits = artifacts.require("ExchangeDeposits"); 10 | const ExchangeGenesis = artifacts.require("ExchangeGenesis"); 11 | const ExchangeTokens = artifacts.require("ExchangeTokens"); 12 | const ExchangeWithdrawals = artifacts.require("ExchangeWithdrawals"); 13 | const Cloneable = artifacts.require("./thirdparty/Cloneable.sol"); 14 | const ExchangeV3 = artifacts.require("./impl/ExchangeV3.sol"); 15 | const LoopringV3 = artifacts.require("LoopringV3"); 16 | const DefaultDepositContract = artifacts.require("DefaultDepositContract"); 17 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 18 | 19 | const LRCToken = artifacts.require("./test/tokens/LRC.sol"); 20 | const GTOToken = artifacts.require("./test/tokens/GTO.sol"); 21 | 22 | const BlockVerifier = artifacts.require("BlockVerifier"); 23 | 24 | module.exports = function(deployer, network, accounts) { 25 | deployer.then(async () => { 26 | const loopringV3 = await LoopringV3.deployed(); 27 | const exchangeV3 = await ExchangeV3.deployed(); 28 | 29 | let pfv = await loopringV3.getProtocolFeeValues(); 30 | console.log("loopringV3.getProtocolFeeValues old", pfv.toString(10)); 31 | 32 | let ePFv = await exchangeV3.getProtocolFeeValues(); 33 | console.log("exchangeV3.getProtocolFeeValues", ePFv.syncedAt.toString(10)); 34 | console.log("exchangeV3.getProtocolFeeValues", ePFv.protocolFeeBips.toString(10)); 35 | console.log("exchangeV3.getProtocolFeeValues", ePFv.previousProtocolFeeBips.toString(10)); 36 | 37 | pfv = 30; 38 | await loopringV3.updateProtocolFeeSettings(pfv); 39 | }); 40 | }; 41 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations/1_initial_migration.js: -------------------------------------------------------------------------------- 1 | var Migrations = artifacts.require("Migrations"); 2 | 3 | module.exports = function(deployer, network, accounts) { 4 | deployer.then(async () => { 5 | await deployer.deploy(Migrations); 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations/2_deploy_thirdparty.js: -------------------------------------------------------------------------------- 1 | const BatchVerifier = artifacts.require("BatchVerifier"); 2 | 3 | module.exports = function(deployer, network, accounts) { 4 | deployer.then(async () => { 5 | await deployer.deploy(BatchVerifier); 6 | }); 7 | }; 8 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations/3_deploy_tokens.js: -------------------------------------------------------------------------------- 1 | // Deploy tokens for testing purposes 2 | 3 | const LRCToken = artifacts.require("./test/tokens/LRC.sol"); 4 | const GTOToken = artifacts.require("./test/tokens/GTO.sol"); 5 | const RDNToken = artifacts.require("./test/tokens/RDN.sol"); 6 | const REPToken = artifacts.require("./test/tokens/REP.sol"); 7 | const WETHToken = artifacts.require("./test/tokens/WETH.sol"); 8 | const TESTToken = artifacts.require("./test/tokens/TEST.sol"); 9 | const INDAToken = artifacts.require("./test/tokens/INDA.sol"); 10 | const INDBToken = artifacts.require("./test/tokens/INDB.sol"); 11 | 12 | module.exports = function(deployer, network, accounts) { 13 | if (network != "live" && network != "live-fork" && network != "goerli") { 14 | deployer.then(async () => { 15 | await deployer.deploy(LRCToken); 16 | await deployer.deploy(GTOToken); 17 | await deployer.deploy(RDNToken); 18 | await deployer.deploy(REPToken); 19 | await deployer.deploy(WETHToken); 20 | await deployer.deploy(TESTToken); 21 | await deployer.deploy(INDAToken); 22 | await deployer.deploy(INDBToken); 23 | 24 | const lrcToken = await LRCToken.deployed(); 25 | const gtoToken = await GTOToken.deployed(); 26 | 27 | if (process.env.TEST_ENV == "docker") { 28 | for (const account of accounts) { 29 | console.log("feed tokens for:", account); 30 | await lrcToken.setBalance(account, "1" + "0".repeat(28)); 31 | await gtoToken.setBalance(account, "1" + "0".repeat(28)); 32 | } 33 | } 34 | }); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations/4_deploy_auxiliaries.js: -------------------------------------------------------------------------------- 1 | // Deploy all auxiliary contracts used by either Exchange, LoopringV3, 2 | // or UniversalRegistry. 3 | 4 | const ProtocolFeeVault = artifacts.require("ProtocolFeeVault"); 5 | // const UserStakingPool = artifacts.require("UserStakingPool"); 6 | const BatchVerifier = artifacts.require("BatchVerifier"); 7 | const BlockVerifier = artifacts.require("BlockVerifier"); 8 | const LRCToken = artifacts.require("./test/tokens/LRC.sol"); 9 | const AgentRegistry = artifacts.require("AgentRegistry"); 10 | const FastWithdrawalAgent = artifacts.require("FastWithdrawalAgent"); 11 | 12 | module.exports = function(deployer, network, accounts) { 13 | if (network != "live" && network != "live-fork" && network != "goerli") { 14 | deployer.then(async () => { 15 | // await deployer.deploy(UserStakingPool, LRCToken.address); 16 | await deployer.deploy(ProtocolFeeVault, LRCToken.address); 17 | 18 | await deployer.link(BatchVerifier, BlockVerifier); 19 | await deployer.deploy(BlockVerifier); 20 | await deployer.deploy(AgentRegistry); 21 | await deployer.deploy(FastWithdrawalAgent); 22 | }); 23 | } else { 24 | deployer.then(async () => { 25 | await deployer.link(BatchVerifier, BlockVerifier); 26 | await deployer.deploy(BlockVerifier); 27 | }); 28 | } 29 | }; 30 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations/5_deploy_protocol_v3.js: -------------------------------------------------------------------------------- 1 | // Deploy protocol: LoopringV3 2 | 3 | const LRCToken = artifacts.require("./test/tokens/LRC.sol"); 4 | const ProtocolFeeVault = artifacts.require("ProtocolFeeVault"); 5 | const BlockVerifier = artifacts.require("BlockVerifier"); 6 | const ExchangeV3 = artifacts.require("ExchangeV3"); 7 | const LoopringV3 = artifacts.require("LoopringV3"); 8 | 9 | module.exports = function(deployer, network, accounts) { 10 | if (network != "live" && network != "live-fork" && network != "goerli") { 11 | deployer.then(async () => { 12 | await deployer.deploy(LoopringV3, LRCToken.address, ProtocolFeeVault.address, BlockVerifier.address); 13 | }); 14 | } else { 15 | const DGTokenAddress = "0x53c8395465a84955c95159814461466053dedede"; // DG token 16 | const ProtocolFeeVaultAddress = "0x7B0d44D5b2eF3A8B168FAfdcc321FAb0D9d5d08C"; // DG HomeDAO 17 | deployer.then(async () => { 18 | await deployer.deploy(LoopringV3, DGTokenAddress, ProtocolFeeVaultAddress, BlockVerifier.address); 19 | }); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations/6_deploy_exchange_v3_libs.js: -------------------------------------------------------------------------------- 1 | // Deploy the ExchangeV3 library which is very large in terms of 2 | // gas usage. We need to deploy most libraries linked from it as stand-alone 3 | // libraries, otherwise we'll run into the 'exceeded block gas limit' issue. 4 | 5 | const ExchangeAdmins = artifacts.require("ExchangeAdmins"); 6 | const ExchangeBalances = artifacts.require("ExchangeBalances"); 7 | const ExchangeBlocks = artifacts.require("ExchangeBlocks"); 8 | const ExchangeDeposits = artifacts.require("ExchangeDeposits"); 9 | const ExchangeGenesis = artifacts.require("ExchangeGenesis"); 10 | const ExchangeTokens = artifacts.require("ExchangeTokens"); 11 | const ExchangeWithdrawals = artifacts.require("ExchangeWithdrawals"); 12 | 13 | module.exports = function(deployer, network, accounts) { 14 | deployer.then(async () => { 15 | await deployer.deploy(ExchangeBalances); 16 | await deployer.link(ExchangeBalances, [ExchangeWithdrawals]); 17 | await deployer.deploy(ExchangeAdmins); 18 | await deployer.deploy(ExchangeTokens); 19 | await deployer.link(ExchangeTokens, [ 20 | ExchangeDeposits, 21 | ExchangeGenesis, 22 | ExchangeWithdrawals 23 | ]); 24 | await deployer.deploy(ExchangeWithdrawals); 25 | await deployer.link(ExchangeWithdrawals, [ExchangeBlocks]); 26 | await deployer.deploy(ExchangeBlocks); 27 | await deployer.deploy(ExchangeGenesis); 28 | await deployer.deploy(ExchangeDeposits); 29 | }); 30 | }; 31 | -------------------------------------------------------------------------------- /packages/loopring_v3/migrations/9_summary.js: -------------------------------------------------------------------------------- 1 | const BatchVerifier = artifacts.require("BatchVerifier"); 2 | const BlockVerifier = artifacts.require("BlockVerifier"); 3 | 4 | const ExchangeAdmins = artifacts.require("ExchangeAdmins"); 5 | const ExchangeBalances = artifacts.require("ExchangeBalances"); 6 | const ExchangeBlocks = artifacts.require("ExchangeBlocks"); 7 | const ExchangeDeposits = artifacts.require("ExchangeDeposits"); 8 | const ExchangeGenesis = artifacts.require("ExchangeGenesis"); 9 | const ExchangeTokens = artifacts.require("ExchangeTokens"); 10 | const ExchangeWithdrawals = artifacts.require("ExchangeWithdrawals"); 11 | const ExchangeV3 = artifacts.require("./impl/ExchangeV3.sol"); 12 | const DefaultDepositContract = artifacts.require("DefaultDepositContract"); 13 | const LoopringIOExchangeOwner = artifacts.require("LoopringIOExchangeOwner"); 14 | const OwnedUpgradabilityProxy = artifacts.require("./thirdparty/proxies/OwnedUpgradabilityProxy"); 15 | 16 | const LoopringV3 = artifacts.require("LoopringV3"); 17 | 18 | module.exports = function(deployer, network, accounts) { 19 | console.log(">>> deployed to network: " + network); 20 | 21 | console.log("- BatchVerifier:", BatchVerifier.address); 22 | console.log("- BlockVerifier:", BlockVerifier.address); 23 | 24 | console.log("- LoopringV3:", LoopringV3.address); 25 | console.log("- ExchangeAdmins:", ExchangeAdmins.address); 26 | console.log("- ExchangeBalances:", ExchangeBalances.address); 27 | console.log("- ExchangeBlocks:", ExchangeBlocks.address); 28 | console.log("- ExchangeDeposits:", ExchangeDeposits.address); 29 | console.log("- ExchangeGenesis:", ExchangeGenesis.address); 30 | console.log("- ExchangeTokens:", ExchangeTokens.address); 31 | console.log("- ExchangeWithdrawals:", ExchangeWithdrawals.address); 32 | console.log("- ExchangeV3Imp:", ExchangeV3.address); 33 | 34 | console.log("- DefaultDepositContractImp:", DefaultDepositContract.address); 35 | console.log("- LoopringIOExchangeOwner:", LoopringIOExchangeOwner.address); 36 | 37 | if (network != "development") { 38 | console.log("- ExchangeV3Proxy:", OwnedUpgradabilityProxy.address); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /packages/loopring_v3/operator/float.py: -------------------------------------------------------------------------------- 1 | from collections import namedtuple 2 | 3 | FloatEncoding = namedtuple("FloatEncoding", "numBitsExponent numBitsMantissa exponentBase") 4 | Float32Encoding = FloatEncoding(7, 25, 10) 5 | Float31Encoding = FloatEncoding(7, 24, 10) 6 | Float30Encoding = FloatEncoding(5, 25, 10) 7 | Float29Encoding = FloatEncoding(5, 24, 10) 8 | Float28Encoding = FloatEncoding(5, 23, 10) 9 | Float24Encoding = FloatEncoding(5, 19, 10) 10 | Float23Encoding = FloatEncoding(5, 18, 10) 11 | Float16Encoding = FloatEncoding(5, 11, 10) 12 | Float12Encoding = FloatEncoding(5, 7, 10) 13 | Float8Encoding = FloatEncoding(5, 3, 10) 14 | 15 | def toFloat(value, floatEncoding): 16 | maxPower = (1 << floatEncoding.numBitsExponent) - 1 17 | maxMantissa = (1 << floatEncoding.numBitsMantissa) - 1 18 | maxExponent = floatEncoding.exponentBase ** maxPower 19 | maxValue = maxMantissa * maxExponent 20 | assert value <= maxValue, "value too large: " 21 | 22 | exponent = 0 23 | r = value // maxMantissa 24 | d = 1 25 | while r >= floatEncoding.exponentBase or d * maxMantissa < value: 26 | r = r // floatEncoding.exponentBase 27 | exponent += 1 28 | d *= floatEncoding.exponentBase 29 | mantissa = value // d 30 | 31 | assert exponent <= maxExponent, "Exponent too large" 32 | assert mantissa <= maxMantissa, "Mantissa too large" 33 | f = (exponent << floatEncoding.numBitsMantissa) + mantissa 34 | return f 35 | 36 | def fromFloat(f, floatEncoding): 37 | exponent = f >> floatEncoding.numBitsMantissa 38 | mantissa = f & ((1 << floatEncoding.numBitsMantissa) - 1) 39 | value = mantissa * (floatEncoding.exponentBase ** exponent) 40 | return value 41 | 42 | def roundToFloatValue(value, encoding): 43 | f = toFloat(int(value), encoding) 44 | floatValue = fromFloat(f, encoding) 45 | return floatValue 46 | 47 | def roundToFloatValueWithNegative(value, encoding): 48 | floatValue = 0 49 | if value > 0: 50 | f = toFloat(int(value), encoding) 51 | floatValue = fromFloat(f, encoding) 52 | else: 53 | f = toFloat(int(-value), encoding) 54 | floatValue = fromFloat(f, encoding) 55 | floatValue = -floatValue 56 | return floatValue -------------------------------------------------------------------------------- /packages/loopring_v3/operator/generate_keys.py: -------------------------------------------------------------------------------- 1 | from create_block import * 2 | import subprocess 3 | 4 | class Struct(object): pass 5 | 6 | def generate_keys(blockType, blockSize): 7 | block = Struct() 8 | block.blockType = blockType 9 | block.blockSize = blockSize 10 | 11 | blockJson = json.dumps(block, default=lambda o: o.__dict__, sort_keys=True, indent=4) 12 | print("blockJson:", blockJson) 13 | 14 | inputFile = "./blocks/block_meta_" + str(blockType) + "_" + str(blockSize) + ".json" 15 | f = open(inputFile, "w+") 16 | f.write(blockJson) 17 | f.close() 18 | subprocess.check_call(["build/circuit/dex_circuit", "-createkeys", inputFile]) 19 | 20 | 21 | if __name__ == "__main__": 22 | # generate keys for blocks with length: [1-16, 32, 64, 96, 128] 23 | size_arr = [*range(1, 17), 32, 64, 96, 128] 24 | # size_arr = [4] # simple test 25 | 26 | for size in size_arr: 27 | for blockType in range(4): 28 | generate_keys(blockType, size, False) 29 | 30 | for size in size_arr: 31 | for blockType in [0, 3]: 32 | generate_keys(blockType, size, True) 33 | -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/DeGate_Report_EN-final2023.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/DeGate_Report_EN-final2023.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/DeGate_Report_EN-final20230912.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/DeGate_Report_EN-final20230912.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/Least Authority - DeGate DAO DeGate Smart Contracts Updated Final Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/Least Authority - DeGate DAO DeGate Smart Contracts Updated Final Audit Report.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/Least Authority - DeGate Technology DeGate zk-SNARK Circuit Final Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/Least Authority - DeGate Technology DeGate zk-SNARK Circuit Final Audit Report.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/Least Authority - Loopring 3.6 Design + Implementation - Circuit Final Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/Least Authority - Loopring 3.6 Design + Implementation - Circuit Final Audit Report.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/Least Authority - Loopring 3.6 Design + Implementation - Smart Contracts Final Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/Least Authority - Loopring 3.6 Design + Implementation - Smart Contracts Final Audit Report.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/LoopringV3_1_Report_CN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/LoopringV3_1_Report_CN.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/LoopringV3_1_Report_EN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/LoopringV3_1_Report_EN.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/LoopringV3_6_vs_V3_1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/LoopringV3_6_vs_V3_1.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/security_audit/Trailofbits - DeGate Final Audit Report.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/degatedev/protocols/be273b45f439f08478ac81bab6b2bc03461a9904/packages/loopring_v3/security_audit/Trailofbits - DeGate Final Audit Report.pdf -------------------------------------------------------------------------------- /packages/loopring_v3/sol-preprocess.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo sol-preprocess $1 4 | 5 | if [ "$1" = "test" ] 6 | then 7 | npx solpp --no-flatten contracts-solpp/IBlockVerifier.solpp -o contracts/core/iface/IBlockVerifier.sol -D Enable_Test_Functions 8 | npx solpp --no-flatten contracts-solpp/BlockVerifier.solpp -o contracts/core/impl/BlockVerifier.sol -D Enable_Test_Functions 9 | 10 | npx solpp --no-flatten contracts-solpp/IExchangeV3.solpp -o contracts/core/iface/IExchangeV3.sol -D Enable_Test_Functions 11 | npx solpp --no-flatten contracts-solpp/ExchangeV3.solpp -o contracts/core/impl/ExchangeV3.sol -D Enable_Test_Functions 12 | 13 | npx solpp --no-flatten contracts-solpp/ExchangeData.solpp -o contracts/core/iface/ExchangeData.sol -D Enable_Test_Functions 14 | else 15 | npx solpp --no-flatten contracts-solpp/IBlockVerifier.solpp -o contracts/core/iface/IBlockVerifier.sol 16 | npx solpp --no-flatten contracts-solpp/BlockVerifier.solpp -o contracts/core/impl/BlockVerifier.sol 17 | 18 | npx solpp --no-flatten contracts-solpp/IExchangeV3.solpp -o contracts/core/iface/IExchangeV3.sol 19 | npx solpp --no-flatten contracts-solpp/ExchangeV3.solpp -o contracts/core/impl/ExchangeV3.sol 20 | 21 | npx solpp --no-flatten contracts-solpp/ExchangeData.solpp -o contracts/core/iface/ExchangeData.sol 22 | fi 23 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/all_16_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0x1a3fabea802788c8aa88741c6a68f271b221eb75838bb1079381f3f1ae414f40", 4 | "0x1e01459c137ae839e99e59b66ac7bb65f59bf2820dd7532ff8640ceb68a7ec65" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x11b35cf2c85531eab64b96eb2eef487e0eb60fb9207fe4763e7f6e02dcead646", 9 | "0x2cbea52f3417b398aed9e355ed16934a81b72d2646e3bf90dbc2dcba294b631d" 10 | ], 11 | [ 12 | "0x2c6518cd26310e541a799357d1ae8bc477b162f2040407b965ecd777e26d31f7", 13 | "0x125170b5860fb8f8da2c43e00ea4a83bcc1a974e47e59fcd657851d2b0dd1655" 14 | ] 15 | ], 16 | "gamma": [ 17 | [ 18 | "0x7ecba8131b3fb354272c86d01577e228c5bd5fb6404bbaf106d7f4858dc2996", 19 | "0x1c5d49a9ae291a2a2213da57a76653391fa1fc0fa7c534afa124ad71b7fdd719" 20 | ], 21 | [ 22 | "0x10f1a73f94a8f077f478d069d7cf1c49444f64cd20ed75d4f6de3d8986147cf8", 23 | "0xd5816f2f116c5cc0be7dfc4c0b4c592204864acb70ad5f789013389a0092ce4" 24 | ] 25 | ], 26 | "delta": [ 27 | [ 28 | "0x10520008be7609bdb92145596ac6bf37da0269f7460e04e8e4701c3afbae0e52", 29 | "0x664e736b2af7bf9125f69fe5c3706cd893cd769b1dae8a6e3d639e2d76e66e2" 30 | ], 31 | [ 32 | "0x1cacce8776f5ada6b35036f9343faab26c91b9aea83d3cb59cf5628ffe18ab1b", 33 | "0x3b48ca7e6d84fca619aaf81745fbf9c30e5a78ed4766cc62b0f12aea5044f56" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x14521453095c890da6f48fdf14b5479a59f067f9c7927f68e66534b095c19d7c", 39 | "0x1154c9da6f65456dc8b32ce8ff50c866f00d999a4c408351cbb71458c12106b" 40 | ], 41 | [ 42 | "0x1a6d270af40a4838666d640496d0650afb3953c610f2c8bda784c3f2aca85409", 43 | "0x26459a1be94a260b130b7b7cc18f95b6b42de3441e421a92655ed3d1020802ec" 44 | ] 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/bitarray.ts: -------------------------------------------------------------------------------- 1 | import BN = require("bn.js"); 2 | 3 | export class BitArray { 4 | private data: number[]; 5 | 6 | constructor(initialData: number[] = []) { 7 | this.data = initialData; 8 | } 9 | 10 | public addBN(value: BN, length: number) { 11 | const res = new Array(length); 12 | for (let i = 0; i < length; i++) { 13 | res[i] = value.testn(i) ? 1 : 0; 14 | } 15 | this.data.push(...res); 16 | } 17 | 18 | public addNumber(value: number, length: number) { 19 | return this.addBN(new BN(value), length); 20 | } 21 | 22 | public addString(value: string, length: number, base: number = 10) { 23 | return this.addBN(new BN(value, base), length); 24 | } 25 | 26 | public getBits() { 27 | return this.data; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/context.ts: -------------------------------------------------------------------------------- 1 | import fs = require("fs"); 2 | import Web3 = require("web3"); 3 | 4 | export class Context { 5 | public blockNumber: number; 6 | public blockTimestamp: number; 7 | public lrcAddress: string; 8 | 9 | public ERC20Contract: any; 10 | 11 | constructor(blockNumber: number, blockTimestamp: number, lrcAddress: string) { 12 | this.blockNumber = blockNumber; 13 | this.blockTimestamp = blockTimestamp; 14 | this.lrcAddress = lrcAddress; 15 | 16 | const ABIPath = "ABI/version36/"; 17 | const erc20Abi = fs.readFileSync(ABIPath + "ERC20.abi", "ascii"); 18 | 19 | /*if (!web3) { 20 | web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); 21 | }*/ 22 | 23 | this.ERC20Contract = new web3.eth.Contract(JSON.parse(erc20Abi)); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/expectThrow.ts: -------------------------------------------------------------------------------- 1 | export async function expectThrow( 2 | promise: Promise, 3 | expectedRevertMessage?: string 4 | ) { 5 | try { 6 | await promise; 7 | } catch (error) { 8 | if (expectedRevertMessage) { 9 | const message = error.message.search(expectedRevertMessage) >= 0; 10 | assert( 11 | message, 12 | "Expected throw with message " + 13 | expectedRevertMessage + 14 | ", got '" + 15 | error + 16 | "' instead" 17 | ); 18 | } else { 19 | const revert = error.message.search("revert") >= 0; 20 | const invalidOpcode = error.message.search("invalid opcode") >= 0; 21 | assert( 22 | revert || invalidOpcode, 23 | "Expected throw, got '" + error + "' instead" 24 | ); 25 | } 26 | return; 27 | } 28 | assert.fail( 29 | "Expected throw not received" + 30 | (expectedRevertMessage ? " (" + expectedRevertMessage + ")" : "") 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/logs.ts: -------------------------------------------------------------------------------- 1 | export function doInfoLogging() { 2 | return process.argv.indexOf("-i") > -1 || doDebugLogging(); 3 | } 4 | 5 | export function doDebugLogging() { 6 | return process.argv.indexOf("-x") > -1; 7 | } 8 | 9 | export function logInfo(...args: any[]) { 10 | if (doInfoLogging()) { 11 | console.log(...args); 12 | } 13 | } 14 | 15 | export function logDebug(...args: any[]) { 16 | if (doDebugLogging()) { 17 | console.log(...args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/testClaimable.ts: -------------------------------------------------------------------------------- 1 | import { expectThrow } from "./expectThrow"; 2 | 3 | const Claimable = artifacts.require("Claimable"); 4 | 5 | contract("Claimable", (accounts: string[]) => { 6 | const owner1 = accounts[0]; 7 | const owner2 = accounts[1]; 8 | const owner3 = accounts[2]; 9 | const emptyAddr = "0x0000000000000000000000000000000000000000"; 10 | 11 | let claimable: any; 12 | 13 | beforeEach(async () => { 14 | claimable = await Claimable.new({ from: owner1 }); 15 | }); 16 | 17 | describe("owner", () => { 18 | it("should be able to transfer ownership", async () => { 19 | await claimable.transferOwnership(owner2, { from: owner1 }); 20 | const contractOwner = await claimable.pendingOwner(); 21 | assert.equal( 22 | contractOwner, 23 | owner2, 24 | "Ownership should be pending for the new owner" 25 | ); 26 | }); 27 | 28 | it("should not be able to transfer ownership to an invalid address", async () => { 29 | await expectThrow( 30 | claimable.transferOwnership(emptyAddr), 31 | "INVALID_ADDRESS" 32 | ); 33 | }); 34 | 35 | it("should not be able to transfer ownership to the current owner", async () => { 36 | await expectThrow(claimable.transferOwnership(owner1), "INVALID_ADDRESS"); 37 | }); 38 | }); 39 | 40 | describe("pending owner", () => { 41 | beforeEach(async () => { 42 | await claimable.transferOwnership(owner2, { from: owner1 }); 43 | }); 44 | 45 | it("should be able to claim ownership", async () => { 46 | await claimable.claimOwnership({ from: owner2 }); 47 | const contractOwner = await claimable.owner(); 48 | assert.equal(contractOwner, owner2, "Owner should match expected value"); 49 | }); 50 | }); 51 | 52 | describe("anyone", () => { 53 | it("should not be able to transfer ownership", async () => { 54 | await expectThrow( 55 | claimable.transferOwnership(owner2, { from: owner2 }), 56 | "UNAUTHORIZED" 57 | ); 58 | }); 59 | 60 | it("should not be able to claim ownership", async () => { 61 | await claimable.transferOwnership(owner2, { from: owner1 }); 62 | await expectThrow( 63 | claimable.claimOwnership({ from: owner3 }), 64 | "UNAUTHORIZED" 65 | ); 66 | }); 67 | }); 68 | }); 69 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/testExchangeAdmin.ts: -------------------------------------------------------------------------------- 1 | import BN = require("bn.js"); 2 | import { expectThrow } from "./expectThrow"; 3 | import { ExchangeTestUtil } from "./testExchangeUtil"; 4 | 5 | contract("Exchange", (accounts: string[]) => { 6 | let exchangeTestUtil: ExchangeTestUtil; 7 | let exchange: any; 8 | let maxAge = 123; 9 | 10 | const createExchange = async (setupTestState: boolean = true) => { 11 | await exchangeTestUtil.createExchange( 12 | exchangeTestUtil.testContext.stateOwners[0], 13 | {setupTestState, useOwnerContract: false} 14 | ); 15 | exchange = exchangeTestUtil.exchange; 16 | }; 17 | 18 | before(async () => { 19 | exchangeTestUtil = new ExchangeTestUtil(); 20 | await exchangeTestUtil.initialize(accounts); 21 | }); 22 | 23 | after(async () => { 24 | await exchangeTestUtil.stop(); 25 | }); 26 | 27 | describe("Admin", function() { 28 | this.timeout(0); 29 | 30 | describe("Exchange owner", () => { 31 | it("should be able to set the max age of a deposit", async () => { 32 | await createExchange(); 33 | await exchange.setMaxAgeDepositUntilWithdrawable(maxAge, { 34 | from: exchangeTestUtil.exchangeOwner 35 | }); 36 | 37 | const maxAgeOnchain = await exchange.getMaxAgeDepositUntilWithdrawable(); 38 | assert.equal(maxAgeOnchain, maxAge, "max age unexpected"); 39 | }); 40 | }); 41 | 42 | describe("anyone", () => { 43 | it("should not be able to set the max age of a deposit", async () => { 44 | await createExchange(); 45 | await expectThrow( 46 | exchange.setMaxAgeDepositUntilWithdrawable(maxAge, { 47 | from: exchangeTestUtil.testContext.orderOwners[0] 48 | }), 49 | "UNAUTHORIZED" 50 | ); 51 | }); 52 | }); 53 | }); 54 | }); 55 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/testExchangeContext.ts: -------------------------------------------------------------------------------- 1 | export class ExchangeTestContext { 2 | public deployer: string; 3 | public stateOwners: string[]; 4 | public operators: string[]; 5 | public orderOwners: string[]; 6 | public wallets: string[]; 7 | 8 | public tokenSymbolAddrMap: Map; // key: symbol, value: addr 9 | public tokenAddrSymbolMap: Map; // key: addr, value: symbol 10 | public tokenAddrDecimalsMap: Map; // key: addr, value: decimals 11 | public tokenAddrInstanceMap: Map; // key: addr, value: contract 12 | public allTokens: any[]; 13 | 14 | constructor( 15 | deployer: string, 16 | stateOwners: string[], 17 | operators: string[], 18 | orderOwners: string[], 19 | wallets: string[], 20 | tokenSymbolAddrMap: Map, 21 | tokenAddrSymbolMap: Map, 22 | tokenAddrDecimalsMap: Map, 23 | tokenAddrInstanceMap: Map, 24 | allTokens: any[] 25 | ) { 26 | this.deployer = deployer; 27 | this.stateOwners = stateOwners; 28 | this.operators = operators; 29 | this.orderOwners = orderOwners; 30 | this.wallets = wallets; 31 | this.tokenSymbolAddrMap = tokenSymbolAddrMap; 32 | this.tokenAddrSymbolMap = tokenAddrSymbolMap; 33 | this.tokenAddrDecimalsMap = tokenAddrDecimalsMap; 34 | this.tokenAddrInstanceMap = tokenAddrInstanceMap; 35 | this.allTokens = allTokens; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/testExchangeShutdown.ts: -------------------------------------------------------------------------------- 1 | import BN = require("bn.js"); 2 | import { expectThrow } from "./expectThrow"; 3 | import { ExchangeTestUtil } from "./testExchangeUtil"; 4 | 5 | contract("Exchange", (accounts: string[]) => { 6 | let ctx: ExchangeTestUtil; 7 | let exchange: any; 8 | let loopringV3: any; 9 | 10 | const createExchange = async () => { 11 | await ctx.createExchange( 12 | ctx.testContext.stateOwners[0], 13 | {useOwnerContract: false} 14 | ); 15 | exchange = ctx.exchange; 16 | }; 17 | 18 | before(async () => { 19 | ctx = new ExchangeTestUtil(); 20 | await ctx.initialize(accounts); 21 | loopringV3 = ctx.loopringV3; 22 | }); 23 | 24 | after(async () => { 25 | await ctx.stop(); 26 | }); 27 | 28 | describe("Shutdown", function() { 29 | this.timeout(0); 30 | 31 | it("Withdraw exchange stake", async () => { 32 | await createExchange(); 33 | 34 | const currentStakeAmount = await exchange.getExchangeStake(); 35 | 36 | // Deposit some LRC to stake for the exchange 37 | const depositer = ctx.testContext.operators[2]; 38 | const stakeAmount = new BN(web3.utils.toWei("1234567", "ether")); 39 | await ctx.setBalanceAndApprove( 40 | depositer, 41 | "LRC", 42 | stakeAmount, 43 | loopringV3.address 44 | ); 45 | 46 | // Stake it 47 | await ctx.depositExchangeStakeChecked( 48 | stakeAmount, 49 | depositer 50 | ); 51 | 52 | // Try to withdraw before the exchange is shutdown 53 | await expectThrow( 54 | exchange.withdrawExchangeStake(ctx.exchangeOwner, { 55 | from: ctx.exchangeOwner 56 | }), 57 | "EXCHANGE_NOT_SHUTDOWN" 58 | ); 59 | 60 | // Shut down the exchange 61 | await exchange.shutdown({ from: ctx.exchangeOwner }); 62 | 63 | // Try to withdraw before the minimum time in shutdown mode has passed 64 | await expectThrow( 65 | exchange.withdrawExchangeStake(ctx.exchangeOwner, { 66 | from: ctx.exchangeOwner 67 | }), 68 | "TOO_EARLY" 69 | ); 70 | 71 | // Wait 72 | await ctx.advanceBlockTimestamp(ctx.MIN_TIME_IN_SHUTDOWN - 100); 73 | 74 | // Try to withdraw before the minimum time in shutdown mode has passed 75 | await expectThrow( 76 | exchange.withdrawExchangeStake(ctx.exchangeOwner, { 77 | from: ctx.exchangeOwner 78 | }), 79 | "TOO_EARLY" 80 | ); 81 | 82 | // Wait 83 | await ctx.advanceBlockTimestamp(200); 84 | 85 | // Withdraw the exchange stake 86 | await ctx.withdrawExchangeStakeChecked( 87 | ctx.exchangeOwner, 88 | currentStakeAmount.add(stakeAmount) 89 | ); 90 | }); 91 | 92 | it("Should not be able to shutdown when already shutdown", async () => { 93 | await createExchange(); 94 | 95 | // Shut down the exchange 96 | await exchange.shutdown({ from: ctx.exchangeOwner }); 97 | 98 | // Try to shut down again 99 | await expectThrow( 100 | exchange.shutdown({ from: ctx.exchangeOwner }), 101 | "ALREADY_SHUTDOWN" 102 | ); 103 | }); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/testExchangeTransfer.ts: -------------------------------------------------------------------------------- 1 | import BN = require("bn.js"); 2 | import { Constants, roundToFloatValue } from "loopringV3.js"; 3 | import { expectThrow } from "./expectThrow"; 4 | import { BalanceSnapshot, ExchangeTestUtil } from "./testExchangeUtil"; 5 | import { AuthMethod, Deposit, SpotTrade, OrderInfo, BatchSpotTrade, BatchSpotTradeUser } from "./types"; 6 | 7 | contract("Exchange", (accounts: string[]) => { 8 | let exchangeTestUtil: ExchangeTestUtil; 9 | let exchange: any; 10 | let depositContract: any; 11 | let loopring: any; 12 | let exchangeID = 0; 13 | 14 | const createExchange = async (setupTestState: boolean = true) => { 15 | exchangeID = await exchangeTestUtil.createExchange( 16 | exchangeTestUtil.testContext.stateOwners[0], 17 | { setupTestState } 18 | ); 19 | exchange = exchangeTestUtil.exchange; 20 | depositContract = exchangeTestUtil.depositContract; 21 | }; 22 | 23 | before(async () => { 24 | exchangeTestUtil = new ExchangeTestUtil(); 25 | await exchangeTestUtil.initialize(accounts); 26 | exchange = exchangeTestUtil.exchange; 27 | loopring = exchangeTestUtil.loopringV3; 28 | depositContract = exchangeTestUtil.depositContract; 29 | exchangeID = 1; 30 | }); 31 | 32 | after(async () => { 33 | await exchangeTestUtil.stop(); 34 | }); 35 | 36 | describe("Transfer", function() { 37 | this.timeout(0); 38 | 39 | it("approved transfer", async () => { 40 | await createExchange(); 41 | 42 | const ownerA = exchangeTestUtil.testContext.orderOwners[0]; 43 | const ownerB = exchangeTestUtil.testContext.orderOwners[1]; 44 | 45 | await exchangeTestUtil.deposit( 46 | ownerA, 47 | ownerA, 48 | "ETH", 49 | new BN(web3.utils.toWei("20", "ether")) 50 | ); 51 | 52 | await exchangeTestUtil.transfer( 53 | ownerA, 54 | ownerB, 55 | "ETH", 56 | new BN(web3.utils.toWei("2", "ether")), 57 | "ETH", 58 | new BN(web3.utils.toWei("0.01", "ether")), 59 | { 60 | authMethod: AuthMethod.EDDSA, 61 | amountToDeposit: new BN(0), 62 | feeToDeposit: new BN(0), 63 | } 64 | ); 65 | 66 | await exchangeTestUtil.transfer( 67 | ownerA, 68 | ownerB, 69 | "ETH", 70 | new BN(web3.utils.toWei("2", "ether")), 71 | "ETH", 72 | new BN(web3.utils.toWei("0.02", "ether")), 73 | { 74 | authMethod: AuthMethod.EDDSA, 75 | useDualAuthoring: true, 76 | amountToDeposit: new BN(0), 77 | feeToDeposit: new BN(0), 78 | } 79 | ); 80 | 81 | await exchangeTestUtil.submitTransactions(8, false); 82 | 83 | // Submit the block 84 | await exchangeTestUtil.submitPendingBlocks(); 85 | }); 86 | 87 | }); 88 | }); 89 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/testOwnable.ts: -------------------------------------------------------------------------------- 1 | import { expectThrow } from "./expectThrow"; 2 | 3 | const Ownable = artifacts.require("Ownable"); 4 | 5 | contract("Ownable", (accounts: string[]) => { 6 | const owner1 = accounts[0]; 7 | const owner2 = accounts[1]; 8 | const emptyAddr = "0x0000000000000000000000000000000000000000"; 9 | 10 | let ownable: any; 11 | 12 | beforeEach(async () => { 13 | ownable = await Ownable.new({ from: owner1 }); 14 | }); 15 | 16 | describe("owner", () => { 17 | it("should be able to transfer ownership", async () => { 18 | await ownable.transferOwnership(owner2, { from: owner1 }); 19 | const contractOwner = await ownable.owner(); 20 | assert.equal(contractOwner, owner2, "Owner should new owner"); 21 | }); 22 | 23 | it("should not be able to transfer ownership to an invalid address", async () => { 24 | await expectThrow(ownable.transferOwnership(emptyAddr), "ZERO_ADDRESS"); 25 | }); 26 | }); 27 | 28 | describe("anyone", () => { 29 | it("should be able to get the owner", async () => { 30 | const contractOwner = await ownable.owner(); 31 | assert.equal(contractOwner, owner1, "Owner should match expected value"); 32 | }); 33 | 34 | it("should not be able to transfer ownership", async () => { 35 | await expectThrow( 36 | ownable.transferOwnership(owner2, { from: owner2 }), 37 | "UNAUTHORIZED" 38 | ); 39 | }); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /packages/loopring_v3/test/testPoseidon.ts: -------------------------------------------------------------------------------- 1 | import BN = require("bn.js"); 2 | import crypto = require("crypto"); 3 | import { Artifacts } from "../util/Artifacts"; 4 | import { Constants, Poseidon } from "loopringV3.js"; 5 | import { expectThrow } from "./expectThrow"; 6 | 7 | contract("Poseidon", (accounts: string[]) => { 8 | let poseidonContract: any; 9 | 10 | const getRand = () => { 11 | const entropy = crypto.randomBytes(32); 12 | return new BN(entropy.toString("hex"), 16).mod(Constants.scalarField); 13 | }; 14 | 15 | before(async () => { 16 | const contracts = new Artifacts(artifacts); 17 | poseidonContract = await contracts.PoseidonContract.new(); 18 | }); 19 | 20 | it("Poseidon t5/f6/p52", async () => { 21 | const hasher = Poseidon.createHash(5, 6, 52); 22 | // Test some random hashes 23 | const numIterations = 128; 24 | for (let i = 0; i < numIterations; i++) { 25 | const t = [getRand(), getRand(), getRand(), getRand()]; 26 | const hash = await poseidonContract.hash_t5f6p52(t[0], t[1], t[2], t[3], new BN(0)); 27 | const expectedHash = hasher(t); 28 | assert.equal(hash, expectedHash, "posseidon hash incorrect"); 29 | } 30 | 31 | // Should not be possible to use an input that is larger than the field 32 | for (let i = 0; i < 5; i++) { 33 | const inputs: BN[] = []; 34 | for (let j = 0; j < 5; j++) { 35 | inputs.push(i === j ? Constants.scalarField : new BN(0)); 36 | } 37 | await expectThrow(poseidonContract.hash_t5f6p52(...inputs), "INVALID_INPUT"); 38 | } 39 | }); 40 | 41 | it("Poseidon t6/f6/p52", async () => { 42 | const hasher = Poseidon.createHash(6, 6, 52); 43 | // Test some random hashes 44 | const numIterations = 128; 45 | for (let i = 0; i < numIterations; i++) { 46 | const t = [getRand(), getRand(), getRand(), getRand(), getRand()]; 47 | const hash = await poseidonContract.hash_t6f6p52(t[0], t[1], t[2], t[3], t[4], new BN(0)); 48 | const expectedHash = hasher(t); 49 | assert.equal(hash, expectedHash, "posseidon hash incorrect"); 50 | } 51 | 52 | // Should not be possible to use an input that is larger than the field 53 | for (let i = 0; i < 6; i++) { 54 | const inputs: BN[] = []; 55 | for (let j = 0; j < 6; j++) { 56 | inputs.push(i === j ? Constants.scalarField : new BN(0)); 57 | } 58 | await expectThrow(poseidonContract.hash_t6f6p52(...inputs), "INVALID_INPUT"); 59 | } 60 | }); 61 | }); 62 | -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_100_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0xe6facbf48de2df5bb321781261a26ff56021f5749d7ba8401e13112c4e19d5e", 19 | "0x1ce4a748d0dcf8d23c7f8be63f63f00d51b25a678ca4624a921152fb748cf86c" 20 | ], 21 | [ 22 | "0x36c8b4f3bd6874e779f193f6217114379df16d7f809af6317300f625a4982cb", 23 | "0x2c20f34172c2f9967410e4f87ef5fd9762863ae19c7b1985d5c9f1809bc60a67" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x2090ef8c5491c2baf7428b9c0c1f1aeb32460c26b4d954b35bb3a12a4b3df549", 39 | "0x1c0c73c198de8479f187cfce4c1d1fdbce68f536b027d268e7b1fe71aec0b676" 40 | ], 41 | [ 42 | "0x16a6944d51df2430055e98eacc630c5c2468ee2b113cde4bcc5a87ed5d189137", 43 | "0xd7a2d3e96e7142ec3a64d0e0dedca10b157816d2c427d30ea224e7aa830daea" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_10_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0x1e198e2fff3966b564ffb0ebc5320562549473f8a73eca0c60be5bf2c2ad1525", 19 | "0x10317cf99c1490a8688aae787a4d999b5e40968f4be3aeff8ee2f70b01dc7cb1" 20 | ], 21 | [ 22 | "0x11a25416f8af0dab48d6df90c1366a305c0faaf63354195055dde2303f99e399", 23 | "0x57ee96b8be30255610664d3d44cc3ac23004562eb8e54a88bea14f403e1e624" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x295333bb1afd7cdc76a7a7288b974767f781ca4ec74c8a47b03106ba85f03316", 39 | "0x11e710442ce6e2371bce43735feb880c983940fd8260352a825d17cf7867721f" 40 | ], 41 | [ 42 | "0x5400210d279975ca9eef7e5050edc3a4ac17528193b0681132000949c6d17b5", 43 | "0xfaf0325be4d0dae754ee460111ccbbd682b13526778843b33ecc26451a77833" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_150_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0x27879c9f6da6f396d310e8d09b69068c0b526eb26ce13b30cf77547384c6615c", 19 | "0x2102deb98c90f54d04f7fc696d74237e74d4743caf1709221ec29d0e756ecb94" 20 | ], 21 | [ 22 | "0x2dcac2eb8424ab71ed3b591a224eecf17bb1ceb251620dd534178a013044542d", 23 | "0x2a857719153a85165aac7ed2ab16130b1c573e506525cf3c77dfff497c5fb4ea" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0xe4a462e04df0c0615e707c9f560f522b37a7bcefb16d1c319eb9f7671d68fc3", 39 | "0x2f05163e032afae03bfc59b49ad5e027e46fb2b84b2343124f23ec5ca4784507" 40 | ], 41 | [ 42 | "0x1355de49751012e6768fdb9d6b06ab8e34b3a7fd6145dc676f525986d09f1415", 43 | "0xbd1e7a99b654f7f0d93386a6e4022788dea7616b350d74bde0f9478c4f82fa8" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_200_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0x198eedc431989efc0bfb61c663102243ffa5d9627f64ddd1a6bdfaf2ba9112b4", 19 | "0xc7ed81bcbf9db286c314f834ff45bc725ad05b1f05100034aa2ea5caad16b5e" 20 | ], 21 | [ 22 | "0x1d391f03e99113d9c7a22a68980afecbf3f98d643c3be32eb71f8320306c2676", 23 | "0x21b968dcd74e5cbd7ca49fc1b9eb62b60f3ff92d2a5f3d4acb397c664fb049b2" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0xf51d88dce7a427af4c9a4a995ff3bca40e0dfe7db21a98dcc6b3383c6f21ed1", 39 | "0x1632e7c03e411b489bb3ab2a78683ed26bb6aa79f5bf4248660de29066a55af1" 40 | ], 41 | [ 42 | "0x28545079e24788b0c10bffdc481bfcc4a2ddf8b229ef7cff83af4076b6193f62", 43 | "0x2306b02455ac1b99c6ed15c21dd67e8be13a14d29d42001ed883a18016b1110d" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_250_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0xd404fea0d7074dfde6a29e5061c4c4ac1c4a8cf813d9a451bcbcaab7b4307be", 19 | "0x254bbadb4190b51a754a009a27584b26b2aa1b50aca7ee56cc3bfbab89d245a2" 20 | ], 21 | [ 22 | "0x255737b9987ddeac3ed6f874246ebfaba471e1092cb4ca9eef65984db0e00f4c", 23 | "0x9367299bbf8c7fb1eed0d5a7dfd1a64a37dbe90ad8a51a45c09819d1ac43ae6" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x18bc11453a808deab7b8e809fa3a19055cb535646566d628e5dbb579b68449c8", 39 | "0x91489488c3fd20f92977143069ebf346f237d2e703dd1ea7261b6c090acc56c" 40 | ], 41 | [ 42 | "0x1d57cce448db120cc69ab36587c28f2c9d6567899fb412da7296d89f0393f303", 43 | "0x99b4b9ab3bfc4fe0b15a51d6dd2e1671f04badfacb5a638bcb7a472f93f85ee" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_25_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0x2033186b14e1582d7bbeb703b768098fe9ebc44ec028b122672e0eef7ec2d1c2", 19 | "0x180629286a61b350437b7bd57a3accc41550a8feb74de879480a44eec9689014" 20 | ], 21 | [ 22 | "0xb94bffec5287720fe3fabb7707fb4c68a09032ed95eb637a3d47cd599066a90", 23 | "0xcfc1e31ae2058f35ae770179a3a551a761c4aa0b22d781da678d8a307449a5e" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x2449fac91ecda0a901b88b5383d3b45e954b90410208584c82f2548b533d9b9f", 39 | "0x1bb5a77938d31da639742e560d0d2d95df58469408b31ec59367ab6d13cf3a7" 40 | ], 41 | [ 42 | "0x2274965b672d75429589900e450fc80191201cafd2e3b59a5a75cb3d49dc6e82", 43 | "0xa575de3c92b12ea2c5efa9959b21b191dd3ebc0bab39597bfb2fc8590f57ba5" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_300_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0x1f7942a8c184687a28a1e5c3e6f218f6b3c11c5dcf4dcca2039e3e0bb1a2af55", 19 | "0xf67433433aafb71550a76e11f584b27de611553ab4775182bb0b8e731b4d9cc" 20 | ], 21 | [ 22 | "0x1c0a73dea2ac149925df8dbd98bc4a060e82dae54dec87f1d23fc1ae5db9aec4", 23 | "0x12c4925e75d5093496261f958cda75cfaabe3d99363f0f9a469019b5543d4136" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x13784794bb8d78e322de6e7495e13ddc28862c8b2c99cc9b2d7dd6c107fd6444", 39 | "0x1bbb7e9952072496237955d446ea9a0cccc718cdb9a75061a4c408a937dddfdd" 40 | ], 41 | [ 42 | "0x6797861839f3d9c5596b7187141cf17a0b5d08f01315f0af6d5f92de50cbd04", 43 | "0x6b1b5f1b842ff9acbebf93aa80ec416431b4dbded9d655dc64e627c665ba31c" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_355_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0x2bafc7375ba76b301bcfa3c3113ccb4aa20df7381765a2deea314e3bbe0e3891", 19 | "0x13316ee58302e17c67eab89f4e35d1ce3795c09fbb56b21867867051f538c41c" 20 | ], 21 | [ 22 | "0x298f897a3cd7aff87e86adba0502ee5b8ce0492fa816c16a4f845cf479d442e3", 23 | "0xad29b79729660add6cadfef6cb6cbc43ae94c04045c2b9fa7a67ce4bd0c406c" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x235cb31871b2a03f64a71ffd108b8fb50ede9c1ab088bec288efc7994df508c0", 39 | "0x104654961701668300f2c15c323d802db1df98c9f4627b9d629ba047b4f8fc80" 40 | ], 41 | [ 42 | "0x1d542d5110f8ec320c53484bee1ad1ba4c193c3bc24f540562649cfbb6525c78", 43 | "0x2e1d3e675946e1c8b8008288e374656021135eb256e7c45f37dc98dfcedcd515" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_50_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0x2069dbc33c265e49622c84cac0e8c0a3fd9dc69b3babbf5f6e57b1a1b4bf388a", 19 | "0x6e19025ae52fd8324a061d74918c4bd96c5da81eb578ababf5b313d88938510" 20 | ], 21 | [ 22 | "0x2f2135c5b9d9646c0e29b6cca02f8b635174bbb16dc67fd20d221160628a02d0", 23 | "0x1866a32fe048da68c0f03d91c60150f583239e7aa26f541b83d4cec413a7f074" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x26770d2318d900db29a011e1c10ecefb3b4b3da0da931a844408c4f9ca08bf2f", 39 | "0x2a9d3ac4ecadbfecce027474b3286dadb25574d1c6c540cf3da0dd136ece651b" 40 | ], 41 | [ 42 | "0x16f3b1425f7db3eae6d73d45b5a06a79bcb79bfd9e5bf6657fcde169d5f63a74", 43 | "0x2cfb5c1de8cd87c0579de4352a32b4078dcaa6bc2f9fb7c34f3a91feff52757a" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/trusted_setup_keys/all_5_vk.json: -------------------------------------------------------------------------------- 1 | { 2 | "alpha": [ 3 | "0xdefef0e62981a7f00b2497f506caf75c4b733a58ddd294d5c6a78283cfe5590", 4 | "0x2a6f18b68a9a02e9a94454e7333d95aa96c0643e149dd97c6bc109a9fd759016" 5 | ], 6 | "beta": [ 7 | [ 8 | "0x18f57047acf209888af5a986629bd7361315e3bb0680cb173e9d1f7b8db0cb6c", 9 | "0x279253d0de1519da31caa2c73f99978a205c4dd2a03e872595d730ffa02bf2de" 10 | ], 11 | [ 12 | "0x2a4cbb21c798002c1573dd1f857bc9bc4e10e7dd4aa3e77b35f72b7cbdeb4c84", 13 | "0x136e466afa727a2dd322331fa4b8fe11067b2df813ae713d1bf9a78a2423e068" 14 | ] 15 | ], 16 | "delta": [ 17 | [ 18 | "0xf31a6aa59ec6af25fa717a04ada5ac207657d53cd4547ecf40594d45f55c816", 19 | "0x1535b1fd444cc9866f34105392ed366b4a9b5372983a202c5bd3ce32bbbfe7bd" 20 | ], 21 | [ 22 | "0xf59f0ce2fad94a9533ec8e24d0f65c40384eefa4fb182e240a61df166a2f436", 23 | "0x13c49ef21b86d0a2bd17cc7bcf41082733b07999d6d869aab7bfa1e44e122514" 24 | ] 25 | ], 26 | "gamma": [ 27 | [ 28 | "0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2", 29 | "0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed" 30 | ], 31 | [ 32 | "0x90689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b", 33 | "0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa" 34 | ] 35 | ], 36 | "gammaABC": [ 37 | [ 38 | "0x105fcae77fcfcfca4616d7c7af7197bdd53371fa6e5b1848153e899444934fa7", 39 | "0x165f52ed93e856889cfd8a5d45bfdc9c31a9f83dcebabe268f189b0bf1d6e391" 40 | ], 41 | [ 42 | "0x173a88309b4fa4df2afc3e8485ed1701e6041ea2c21b72a057d9df34ed2a21e3", 43 | "0x1cffdc306cc9b967039773c869b06a497b802c1644ea57d652a952df5225c3f9" 44 | ] 45 | ] 46 | } -------------------------------------------------------------------------------- /packages/loopring_v3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "esModuleInterop": true, 5 | "outDir": "./transpiled/", 6 | "sourceMap": true, 7 | "noImplicitAny": true, 8 | "module": "commonjs", 9 | "target": "es6", 10 | "baseUrl": ".", 11 | "allowJs": true 12 | }, 13 | "include": [ 14 | "node_modules/loopringV3.js/index.ts", 15 | "node_modules/loopringV3.js/src/**/*", 16 | "./globals.d.ts", 17 | "./util/**/*", 18 | "./test/**/*", 19 | "./migrations/**/*" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/loopring_v3/util/Artifacts.ts: -------------------------------------------------------------------------------- 1 | export class Artifacts { 2 | public MockContract: any; 3 | public LoopringV3: any; 4 | public ExchangeV3: any; 5 | public BlockVerifier: any; 6 | public DummyToken: any; 7 | public LRCToken: any; 8 | public GTOToken: any; 9 | public RDNToken: any; 10 | public REPToken: any; 11 | public WETHToken: any; 12 | public INDAToken: any; 13 | public INDBToken: any; 14 | public TESTToken: any; 15 | public TestAccountContract: any; 16 | public TransferContract: any; 17 | public PoseidonContract: any; 18 | // public UserStakingPool: any; 19 | public ProtocolFeeVault: any; 20 | // public UniswapTokenSeller: any; 21 | public AddressWhitelist: any; 22 | public DelayedOwnerContract: any; 23 | public DelayedTargetContract: any; 24 | public DefaultDepositContract: any; 25 | public OwnedUpgradabilityProxy: any; 26 | public ChiToken: any; 27 | 28 | constructor(artifacts: any) { 29 | this.MockContract = artifacts.require("MockContract"); 30 | this.LoopringV3 = artifacts.require("LoopringV3"); 31 | this.ExchangeV3 = artifacts.require("ExchangeV3"); 32 | this.BlockVerifier = artifacts.require("BlockVerifier"); 33 | 34 | this.DummyToken = artifacts.require("test/DummyToken"); 35 | this.LRCToken = artifacts.require("test/tokens/LRC"); 36 | this.GTOToken = artifacts.require("test/tokens/GTO"); 37 | this.RDNToken = artifacts.require("test/tokens/RDN"); 38 | this.REPToken = artifacts.require("test/tokens/REP"); 39 | this.WETHToken = artifacts.require("test/tokens/WETH"); 40 | this.INDAToken = artifacts.require("test/tokens/INDA"); 41 | this.INDBToken = artifacts.require("test/tokens/INDB"); 42 | this.TESTToken = artifacts.require("test/tokens/TEST"); 43 | this.TestAccountContract = artifacts.require("TestAccountContract"); 44 | this.TransferContract = artifacts.require("TransferContract"); 45 | this.PoseidonContract = artifacts.require("PoseidonContract"); 46 | // this.UserStakingPool = artifacts.require("UserStakingPool"); 47 | this.ProtocolFeeVault = artifacts.require("ProtocolFeeVault"); 48 | this.DelayedOwnerContract = artifacts.require("DelayedOwnerContract"); 49 | this.DelayedTargetContract = artifacts.require("DelayedTargetContract"); 50 | this.DefaultDepositContract = artifacts.require("DefaultDepositContract"); 51 | this.OwnedUpgradabilityProxy = artifacts.require("OwnedUpgradabilityProxy"); 52 | // this.ChiToken = artifacts.require("ChiToken"); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/loopring_v3/util/TimeTravel.ts: -------------------------------------------------------------------------------- 1 | let advanceTimeAsync = (time: number) => { 2 | return new Promise((resolve, reject) => { 3 | web3.currentProvider.send( 4 | { 5 | jsonrpc: "2.0", 6 | method: "evm_increaseTime", 7 | params: [time], 8 | id: new Date().getTime() 9 | }, 10 | (err: string, result: any) => { 11 | if (err) { 12 | return reject(err); 13 | } 14 | return resolve(result); 15 | } 16 | ); 17 | }); 18 | }; 19 | 20 | let advanceBlockAsync = () => { 21 | return new Promise((resolve, reject) => { 22 | web3.currentProvider.send( 23 | { 24 | jsonrpc: "2.0", 25 | method: "evm_mine", 26 | id: new Date().getTime() 27 | }, 28 | (err: string) => { 29 | if (err) { 30 | return reject(err); 31 | } 32 | const newBlockHash = web3.eth.getBlock("latest").hash; 33 | return resolve(newBlockHash); 34 | } 35 | ); 36 | }); 37 | }; 38 | 39 | let advanceTimeAndBlockAsync = async (time: number) => { 40 | await advanceTimeAsync(time); 41 | await advanceBlockAsync(); 42 | 43 | return Promise.resolve(web3.eth.getBlock("latest")); 44 | }; 45 | 46 | export { advanceTimeAsync, advanceBlockAsync, advanceTimeAndBlockAsync }; 47 | -------------------------------------------------------------------------------- /packages/loopring_v3/util/generate_keys_contract.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import json 3 | from datetime import datetime 4 | from pytz import reference 5 | 6 | # block settings 7 | block_type = 0 8 | block_sizes = [384, 256, 128, 64, 32, 16] 9 | block_version = 32 10 | 11 | # keys path 12 | keys_path = "./trusted_setup_keys/" 13 | # output 14 | output_filename = "./contracts/core/impl/VerificationKeys.sol" 15 | 16 | 17 | def to_hex(d): 18 | return hex(int(d)).rstrip('L') 19 | 20 | def from_hex(h): 21 | return int(h, 16) 22 | 23 | now = datetime.now() 24 | localtime = reference.LocalTimezone() 25 | 26 | o = "" 27 | o = o + "// SPDX-License-Identifier: Apache-2.0\n" 28 | o = o + "// Copyright 2017 Loopring Technology Limited.\n" 29 | o = o + "pragma solidity ^0.7.0;\n" 30 | o = o + "\n" 31 | o = o + "\n" 32 | o = o + "/// @title Hard coded verification keys\n" 33 | o = o + "/// @dev Generated on " + now.strftime("%d-%b-%Y %H:%M:%S, " + localtime.tzname(now)) + "\n" 34 | o = o + "/// @author Brecht Devos - \n" 35 | o = o + "library VerificationKeys\n" 36 | o = o + "{\n" 37 | o = o + " function getKey(\n" 38 | o = o + " uint blockType,\n" 39 | o = o + " uint blockSize,\n" 40 | o = o + " uint blockVersion\n" 41 | o = o + " )\n" 42 | o = o + " internal\n" 43 | o = o + " pure\n" 44 | o = o + " returns (uint[14] memory vk, uint[4] memory vk_gammaABC, bool found)\n" 45 | o = o + " {\n" 46 | 47 | for i in range(len(block_sizes)): 48 | f = json.load(open(keys_path + "all_" + str(block_sizes[i]) + "_vk.json")) 49 | 50 | values = f["alpha"] + f["beta"][0] + f["beta"][1] + f["gamma"][0] + f["gamma"][1] + f["delta"][0] + f["delta"][1] + f["gammaABC"][0] + f["gammaABC"][1] 51 | values = list(map(from_hex, values)) 52 | 53 | vk = values[:14] 54 | vk_gammaABC = values[14:] 55 | 56 | o = o + " " + ("" if i == 0 else "} else ") + "if (blockType == 0 && blockSize == " + str(block_sizes[i]) + " && blockVersion == " + str(block_version) + ") {\n" 57 | 58 | o = o + " vk = [\n" 59 | for i in range(len(vk)): 60 | o = o + " " + str(vk[i]) + ("" if i == len(vk) - 1 else ",") + "\n" 61 | o = o + " ];\n" 62 | 63 | o = o + " vk_gammaABC = [\n" 64 | for i in range(len(vk_gammaABC)): 65 | o = o + " " + str(vk_gammaABC[i]) + ("" if i == len(vk_gammaABC) - 1 else ",") + "\n" 66 | o = o + " ];\n" 67 | 68 | o = o + " found = true;\n" 69 | 70 | o = o + " } else {\n" 71 | o = o + " found = false;\n" 72 | o = o + " }\n" 73 | o = o + " }\n" 74 | o = o + "}\n" 75 | 76 | f3 = open(output_filename, 'w') 77 | f3.write(o) 78 | f3.close() 79 | 80 | print(output_filename + " updated.") 81 | -------------------------------------------------------------------------------- /packages/loopring_v3/verify_all_contracts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TRUFFLE_CMD="./node_modules/.bin/truffle" 4 | declare -a ALL_CONTRACTS=(Cloneable \ 5 | BatchVerifier \ 6 | UniversalRegistry \ 7 | ProtocolFeeVault \ 8 | UniswapTokenSeller \ 9 | UserStakingPool \ 10 | BlockVerifier \ 11 | ExchangeAdmins \ 12 | ExchangeBalances \ 13 | ExchangeBlocks \ 14 | ExchangeDeposits \ 15 | ExchangeGenesis \ 16 | ExchangeTokens \ 17 | ExchangeWithdrawals \ 18 | ExchangeV3 \ 19 | LoopringV3\ 20 | ) 21 | 22 | for contract in "${ALL_CONTRACTS[@]}" 23 | do 24 | $TRUFFLE_CMD run verify "$contract" --network live 25 | done 26 | 27 | echo "All contracts verified!" 28 | 29 | --------------------------------------------------------------------------------