diff --git a/contracts/BrokerRegistry.sol b/contracts/BrokerRegistry.sol new file mode 100644 index 00000000..3daf3e96 --- /dev/null +++ b/contracts/BrokerRegistry.sol @@ -0,0 +1,72 @@ +/* + + Copyright 2017 Loopring Project Ltd (Loopring Foundation). + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +pragma solidity 0.4.23; +pragma experimental "v0.5.0"; +pragma experimental "ABIEncoderV2"; + + +/// @title Trade Broker +/// @dev A broker is an account that can submit order on behalf of other +/// accounts. When register a broker, the owner can also specify a +/// pre-deployed BrokageTracker to manage the allowance of for the +/// specific broker. +/// @author Daniel Wang - . +contract BrokerRegistry { + event BrokerRegistered( + address owner, + address broker, + address tracker + ); + + event BrokerUnregistered( + address owner, + address broker + ); + + function getBroker( + address owner, + address broker + ) + external + view + returns( + bool authenticated, + address tracker + ); + + function getBrokers( + uint start, + uint count + ) + public + view + returns ( + address[] brokers, + address[] trackers + ); + + function registerBroker( + address broker, + address tracker // 0x0 allowed + ) + external; + + function unregisterBroker( + address broker + ) + external; +} diff --git a/contracts/BrokerRegistryImpl.sol b/contracts/BrokerRegistryImpl.sol new file mode 100644 index 00000000..e8ac9b0d --- /dev/null +++ b/contracts/BrokerRegistryImpl.sol @@ -0,0 +1,147 @@ +/* + + Copyright 2017 Loopring Project Ltd (Loopring Foundation). + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +pragma solidity 0.4.23; +pragma experimental "v0.5.0"; +pragma experimental "ABIEncoderV2"; + +import "./BrokerRegistry.sol"; + + +/// @title An Implementation of BrokerRegistry. +/// @author Daniel Wang - . +contract BrokerRegistryImpl is BrokerRegistry { + struct Broker { + uint pos; // 0 mens unregistered; if > 0, pos - 1 is the + // token's position in `addresses`. + address owner; + address addr; + address tracker; + } + + mapping(address => Broker[]) public brokerageMap; + mapping(address => mapping(address => Broker)) public brokerMap; + + function getBroker( + address owner, + address broker + ) + external + view + returns( + bool authenticated, + address tracker + ) + { + Broker storage b = brokerMap[owner][broker]; + authenticated = (b.addr != 0x0); + tracker = b.tracker; + } + + function getBrokers( + uint start, + uint count + ) + public + view + returns ( + address[] brokers, + address[] trackers + ) + { + Broker[] storage _brokers = brokerageMap[msg.sender]; + uint num = _brokers.length; + + if (start >= num) { + return; + } + + uint end = start + count; + if (end > num) { + end = num; + } + + if (start == num) { + return; + } + + brokers = new address[](end - start); + trackers = new address[](end - start); + for (uint i = start; i < end; i++) { + brokers[i - start] = _brokers[i].addr; + trackers[i - start] = _brokers[i].tracker; + } + } + + function registerBroker( + address broker, + address tracker // 0x0 allowed + ) + external + { + require(0x0 != broker,"bad broker"); + require( + 0 == brokerMap[msg.sender][broker].pos, + "broker already exists" + ); + + Broker[] storage brokers = brokerageMap[msg.sender]; + Broker memory b = Broker( + brokers.length + 1, + msg.sender, + broker, + tracker + ); + + brokers.push(b); + brokerMap[msg.sender][broker] = b; + + emit BrokerRegistered( + msg.sender, + broker, + tracker + ); + } + + function unregisterBroker( + address broker + ) + external + { + require(0x0 != broker, "bad broker"); + require( + brokerMap[msg.sender][broker].addr == broker, + "broker not found" + ); + + Broker storage b = brokerMap[msg.sender][broker]; + delete brokerMap[msg.sender][broker]; + + Broker[] storage brokers = brokerageMap[msg.sender]; + Broker storage lastBroker = brokers[brokers.length - 1]; + + if (lastBroker.addr != broker) { + // Swap with the last token and update the pos + lastBroker.pos = b.pos; + brokers[b.pos - 1] = lastBroker; + brokerMap[lastBroker.owner][lastBroker.addr] = lastBroker; + } + + brokers.length--; + + emit BrokerUnregistered(msg.sender, broker); + } +} diff --git a/contracts/BrokerTracker.sol b/contracts/BrokerTracker.sol new file mode 100644 index 00000000..55c9247c --- /dev/null +++ b/contracts/BrokerTracker.sol @@ -0,0 +1,54 @@ +/* + + Copyright 2017 Loopring Project Ltd (Loopring Foundation). + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +pragma solidity 0.4.23; +pragma experimental "v0.5.0"; +pragma experimental "ABIEncoderV2"; + + +/// @title BrokerTracker +contract BrokerTracker { + /// @dev Returns the max amount the broker can buy or sell. + function getAllowance( + address owner, + address broker, + address tokenB, + address tokenS + ) + public + view + returns ( + uint allowanceB, + uint allowanceS, + uint lrcAllowance + ); + + /// @dev This method will be called from TokenTransferDelegateImpl, so + /// it must check `msg.sender` is the address of LoopringProtocol. + /// Check https://github.com/Loopring/token-listing/blob/master/ethereum/deployment.md + /// for the current address of LoopringProtocol deployment. + function onSettlement( + address owner, + address broker, + address tokenB, + uint amountB, + address tokenS, + uint amountS, + uint lrcFee, + uint lrcReward + ) + public; +} \ No newline at end of file diff --git a/contracts/LoopringProtocolImpl.sol b/contracts/LoopringProtocolImpl.sol index 9b780535..6830a45d 100644 --- a/contracts/LoopringProtocolImpl.sol +++ b/contracts/LoopringProtocolImpl.sol @@ -21,6 +21,8 @@ pragma experimental "ABIEncoderV2"; import "./lib/AddressUtil.sol"; import "./lib/ERC20.sol"; import "./lib/MathUint.sol"; +import "./BrokerRegistry.sol"; +import "./BrokerTracker.sol"; import "./LoopringProtocol.sol"; import "./TokenRegistry.sol"; import "./TokenTransferDelegate.sol"; diff --git a/contracts/TokenRegistryImpl.sol b/contracts/TokenRegistryImpl.sol index 81160cd4..81c811df 100644 --- a/contracts/TokenRegistryImpl.sol +++ b/contracts/TokenRegistryImpl.sol @@ -34,7 +34,7 @@ contract TokenRegistryImpl is TokenRegistry, Claimable { mapping (string => address) symbolMap; struct TokenInfo { - uint pos; // 0 mens unregistered; if > 0, pos + 1 is the + uint pos; // 0 mens unregistered; if > 0, pos - 1 is the // token's position in `addresses`. string symbol; // Symbol of the token } @@ -170,6 +170,17 @@ contract TokenRegistryImpl is TokenRegistry, Claimable { } } + // address[] public addresses; + // mapping (address => TokenInfo) addressMap; + // mapping (string => address) symbolMap; + + // struct TokenInfo { + // uint pos; // 0 mens unregistered; if > 0, pos - 1 is the + // // token's position in `addresses`. + // string symbol; // Symbol of the token + // } + + function registerTokenInternal( address addr, string symbol