Transactions
Internal Transactions
Coin Balance History
Code
Read Contract
Read Proxy
Write Contract
Write Proxy
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- TokenManagerDelegateV2
- Optimization enabled
- true
- Compiler version
- v0.4.26+commit.4563c3fc
- Optimization runs
- 200
- Verified at
- 2023-04-20T02:12:54.636931Z
contracts/tokenManager/TokenManagerDelegateV2.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; pragma experimental ABIEncoderV2; import "../interfaces/IWrappedNFT721.sol"; import "../interfaces/IWrappedNFT1155.sol"; import "../interfaces/IMappingToken.sol"; import "./MappingToken.sol"; import "./TokenManagerDelegate.sol"; import "../components/Proxy.sol"; contract TokenManagerDelegateV2 is TokenManagerDelegate, Proxy { /************************************************************ ** ** STATE VARIABLES ** ************************************************************/ address public operator; /// tokenPairID => type; type: 0 is ERC20, 1 is ERC721, ... enum TokenCrossType {ERC20, ERC721, ERC1155} mapping(uint => uint8) public mapTokenPairType; /************************************************************ ** ** EVENTS ** ************************************************************/ event SetOperator(address indexed oldOperator, address indexed newOperator); event SetTokenPairType(uint indexed tokenPairId, uint indexed tokenPairType); /** * * MODIFIERS * */ modifier onlyOperator() { require(msg.sender == operator, "not operator"); _; } /************************************************************ ** ** MANIPULATIONS ** ************************************************************/ function setTokenPairTypes(uint[] tokenPairIds, uint8[] tokenPairTypes) external onlyOperator { require(tokenPairIds.length == tokenPairTypes.length, "length mismatch"); for(uint idx = 0; idx < tokenPairIds.length; ++idx) { mapTokenPairType[tokenPairIds[idx]] = tokenPairTypes[idx]; emit SetTokenPairType(tokenPairIds[idx], tokenPairTypes[idx]); } } function setOperator(address account) external onlyOwner { emit SetOperator(operator, account); operator = account; } //***************************************************************************** //***************************************************************************** // ERC1155 //***************************************************************************** //***************************************************************************** function mintNFT( uint tokenCrossType, address tokenAddress, address to, uint[] tokenIDs, uint[] values, bytes data ) public onlyAdmin { if(tokenCrossType == uint(TokenCrossType.ERC721)) { IWrappedNFT721(tokenAddress).mintBatch(to, tokenIDs, data); } else if(tokenCrossType == uint(TokenCrossType.ERC1155)) { IWrappedNFT1155(tokenAddress).mintBatch(to, tokenIDs, values, data); } else { require(false, "Invalid NFT type"); } } function burnNFT( uint tokenCrossType, address tokenAddress, address from, uint[] tokenIDs, uint[] values ) public onlyAdmin { if(tokenCrossType == uint(TokenCrossType.ERC721)) { IWrappedNFT721(tokenAddress).burnBatch(from, tokenIDs); } else if(tokenCrossType == uint(TokenCrossType.ERC1155)) { IWrappedNFT1155(tokenAddress).burnBatch(from, tokenIDs, values); } else { require(false, "Invalid NFT type"); } } }
openzeppelin-eth/contracts/token/ERC721/IERC721Enumerable.sol
pragma solidity ^0.4.24; import "../../zos-lib/Initializable.sol"; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721Enumerable is Initializable, IERC721 { function totalSupply() public view returns (uint256); function tokenOfOwnerByIndex( address owner, uint256 index ) public view returns (uint256 tokenId); function tokenByIndex(uint256 index) public view returns (uint256); }
contracts/storemanGroupAdmin/IncentiveLib.sol
pragma solidity ^0.4.24; import "./StoremanType.sol"; import "../interfaces/IPosLib.sol"; import "../interfaces/IMetric.sol"; import "../interfaces/IListGroup.sol"; import "./StoremanUtil.sol"; library IncentiveLib { using Deposit for Deposit.Records; using SafeMath for uint; uint public constant DIVISOR = 10000; event incentiveEvent(bytes32 indexed groupId, address indexed wkAddr, bool indexed finished, uint from, uint end); event selectedEvent(bytes32 indexed groupId, uint indexed count, address[] members); function getChainTypeCo(StoremanType.StoremanData storage data, uint chain1, uint chain2) public view returns(uint co){ if(chain1 < chain2) { co = data.chainTypeCo[chain1][chain2]; } else { co = data.chainTypeCo[chain2][chain1]; } if(co == 0){ return data.conf.chainTypeCoDefault; } return co; } function getGroupIncentive(address groupListAddr, StoremanType.StoremanGroup storage group, uint day,StoremanType.StoremanData storage data) private view returns (uint) { uint chainTypeCo = getChainTypeCo(data,group.chain1, group.chain2); uint totalDeposit = IListGroup(groupListAddr).getTotalDeposit(day); if(totalDeposit == 0){ bytes32[] memory groupIds = IListGroup(groupListAddr).getActiveGroupIds(day); for(uint i=0; i<groupIds.length; i++){ totalDeposit = totalDeposit.add(data.groups[groupIds[i]].deposit.getValueById(day)); } require(totalDeposit != 0, "internal error"); IListGroup(groupListAddr).setTotalDeposit(day, totalDeposit); } return IPosLib(data.posLib).getMinIncentive(group.deposit.getLastValue(),day, totalDeposit).mul(chainTypeCo).div(DIVISOR); } function calIncentive(uint groupIncentive, uint groupWeight, uint weight) private returns (uint) { return groupIncentive.mul(weight).div(groupWeight); } function checkMetric(IMetric metric, bytes32 groupId, uint day, uint index) private returns (bool) { if(index == 0) { return true; // leader is always OK. } uint[] memory counts = metric.getPrdInctMetric(groupId, day, day); uint leadCount = counts[0]; if(leadCount < 6) { return true; } uint nodeCount = counts[index]; if(nodeCount >= leadCount/2){ return true; } return false; } function rotateSkGroup(address posLib, StoremanType.Candidate storage sk, StoremanType.StoremanGroup storage group) public { if(sk.incentivedDay+1 == StoremanUtil.getDaybyTime(posLib, group.workTime+group.totalTime) && group.status == StoremanType.GroupStatus.dismissed) { if(sk.nextGroupId != bytes32(0x00)) { sk.groupId = sk.nextGroupId; sk.nextGroupId = bytes32(0x00); } else { // if whitelist, set groupId = 0 if(sk.isWhite){ sk.groupId = bytes32(0x00); } } } } function calFromEndDay(address posLib, StoremanType.Candidate storage sk, StoremanType.StoremanGroup storage group) private returns(uint,uint) { uint fromDay = StoremanUtil.getDaybyTime(posLib, group.workTime); if (fromDay <= sk.incentivedDay){ fromDay = sk.incentivedDay + 1; } uint endDay = now; if (endDay > group.workTime + group.totalTime) { endDay = group.workTime + group.totalTime; } endDay = StoremanUtil.getDaybyTime(posLib, endDay); return (fromDay, endDay); } function checkPartQuited(address listGroupAddr, StoremanType.Candidate storage sk, address pnAddr) private view returns(bool){ bytes32 QuitGroupId; bytes32 QuitNextGroupId; (QuitGroupId,QuitNextGroupId) = IListGroup(listGroupAddr).getPartQuitGroupId(sk.wkAddr, pnAddr); StoremanType.Delegator storage pn = sk.partners[pnAddr]; if(pn.quited && QuitGroupId != sk.groupId && QuitNextGroupId != sk.groupId){ return true; } return false; } function checkDelegateQuited(address listGroupAddr, StoremanType.Candidate storage sk, address deAddr) private view returns(bool){ bytes32 QuitGroupId; bytes32 QuitNextGroupId; (QuitGroupId,QuitNextGroupId) = IListGroup(listGroupAddr).getDelegateQuitGroupId(sk.wkAddr, deAddr); StoremanType.Delegator storage de = sk.delegators[deAddr]; if(de.quited && QuitGroupId != sk.groupId && QuitNextGroupId != sk.groupId){ return true; } return false; } function incentiveNode(uint day, StoremanType.Candidate storage sk, StoremanType.StoremanGroup storage group,StoremanType.StoremanData storage data, address listGroupAddr) public { sk.incentive[day] = calIncentive(group.groupIncentive[day], group.depositWeight.getValueById(day), StoremanUtil.calSkWeight(data.conf.standaloneWeight,sk.deposit.getValueById(day))); sk.incentive[0] = sk.incentive[0].add(sk.incentive[day]); data.totalReward = data.totalReward.add(sk.incentive[day]); for(uint m=0; m<sk.partnerCount; m++){ if(checkPartQuited(listGroupAddr, sk, sk.partMap[m])){ continue; } uint partnerWeight = StoremanUtil.calSkWeight(data.conf.standaloneWeight, sk.partners[sk.partMap[m]].deposit.getValueById(day)); uint partnerReward = calIncentive(group.groupIncentive[day], group.depositWeight.getValueById(day), partnerWeight); sk.incentive[day] = sk.incentive[day].add(partnerReward); sk.incentive[0] = sk.incentive[0].add(partnerReward); data.totalReward = data.totalReward.add(partnerReward); } } function incentiveDelegator(uint day, StoremanType.Candidate storage sk, StoremanType.StoremanGroup storage group,StoremanType.StoremanData storage data, address listGroupAddr) public { address deAddr = sk.delegatorMap[sk.incentivedDelegator]; if(checkDelegateQuited(listGroupAddr, sk, deAddr)){ sk.incentivedDelegator++; return; } uint incs = calIncentive(group.groupIncentive[day], group.depositWeight.getValueById(day), sk.delegators[deAddr].deposit.getValueById(day)); uint incSk = incs.mul(group.delegateFee).div(DIVISOR); uint incDe = incs.sub(incSk); sk.delegators[deAddr].incentive[day] = sk.delegators[deAddr].incentive[day].add(incDe); sk.delegators[deAddr].incentive[0] = sk.delegators[deAddr].incentive[0].add(incDe); sk.incentive[day] = sk.incentive[day].add(incSk); sk.incentive[0] = sk.incentive[0].add(incSk); data.totalReward = data.totalReward.add(incs); sk.incentivedDelegator++; } /* @dev The logic of incentive 1) get the incentive by day and groupID. If the incentive array by day haven't got from low level, the tx will try to get it. so the one who first incentive will spend more gas. 2) calculate the sk incentive every days. 3) calculate the delegator every days one by one. */ function incentiveCandidator(StoremanType.StoremanData storage data, address wkAddr, address metricAddr, address listGroupAddr) public { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.StoremanGroup storage group = data.groups[sk.groupId]; require(group.status >= StoremanType.GroupStatus.ready, "not ready"); uint fromDay; uint endDay; uint reservedGas = 2500000; (fromDay, endDay) = calFromEndDay(data.posLib, sk, group); uint day; uint idx = 0; for (; idx < group.selectedCount; idx++) { address addr = group.selectedNode[idx]; if (addr == sk.wkAddr) { break; } } require(idx < group.selectedCount, "not selected"); for (day = fromDay; day < endDay; day++) { if (msg.gas < reservedGas ) { // check the gas. because calculate delegator incentive need more gas left. emit incentiveEvent(sk.groupId, wkAddr, false, fromDay, day); return; } if (group.groupIncentive[day] == 0) { group.groupIncentive[day] = getGroupIncentive(listGroupAddr, group, day, data); } if(checkMetric(IMetric(metricAddr), sk.groupId, day, idx)){ if(0 == sk.incentive[day]) { incentiveNode(day, sk,group,data, listGroupAddr); } while (sk.incentivedDelegator < sk.delegatorCount) { if (msg.gas < reservedGas ) { emit incentiveEvent(sk.groupId, wkAddr, false, fromDay, 0); return; } incentiveDelegator(day, sk,group,data,listGroupAddr); } } sk.incentivedDay = day; rotateSkGroup(data.posLib, sk, group); sk.incentivedDelegator = 0; } emit incentiveEvent(sk.groupId, wkAddr, true, fromDay, endDay-1); } function setGroupDeposit(StoremanType.StoremanData storage data,StoremanType.StoremanGroup storage group) public { uint day = StoremanUtil.getDaybyTime(data.posLib, group.workTime); uint groupDeposit = 0; uint groupDepositWeight = 0; for(uint i = 0; i<group.memberCountDesign; i++){ StoremanType.Candidate storage sk = data.candidates[0][group.selectedNode[i]]; groupDeposit = groupDeposit.add(sk.deposit.getLastValue().add(sk.partnerDeposit).add(sk.delegateDeposit)); groupDepositWeight = groupDepositWeight.add(StoremanUtil.calSkWeight(data.conf.standaloneWeight,sk.deposit.getLastValue().add(sk.partnerDeposit)).add(sk.delegateDeposit)); } Deposit.Record memory deposit = Deposit.Record(day, groupDeposit); Deposit.Record memory depositWeight = Deposit.Record(day, groupDepositWeight); group.deposit.clean(); group.depositWeight.clean(); group.deposit.addRecord(deposit); group.depositWeight.addRecord(depositWeight); return; } function cleanSmNode(StoremanType.Candidate storage skt, bytes32 groupId){ if(skt.isWhite){ if(skt.groupId == groupId){ skt.groupId = bytes32(0x00); }else if(skt.nextGroupId == groupId){ skt.nextGroupId = bytes32(0x00); } } } function toSelect(StoremanType.StoremanData storage data,bytes32 groupId) public { StoremanType.StoremanGroup storage group = data.groups[groupId]; require(group.status == StoremanType.GroupStatus.curveSeted,"Wrong status"); require(now > group.registerTime + group.registerDuration, "Wrong time"); if(group.memberCount < group.memberCountDesign){ group.status = StoremanType.GroupStatus.failed; for(uint k=0; k<group.whiteCountAll; k++){ StoremanType.Candidate storage skt = data.candidates[0][group.whiteMap[k]]; cleanSmNode(skt, groupId); } return; } address[] memory members = new address[](group.memberCountDesign); for(uint i = 0; i<group.memberCountDesign; i++){ members[i] = group.selectedNode[i]; } emit selectedEvent(groupId, group.memberCountDesign, members); group.status = StoremanType.GroupStatus.selected; setGroupDeposit(data,group); return; } }
contracts/interfaces/ITokenManager.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; interface ITokenManager { function getTokenPairInfo(uint id) external view returns (uint origChainID, bytes tokenOrigAccount, uint shadowChainID, bytes tokenShadowAccount); function getTokenPairInfoSlim(uint id) external view returns (uint origChainID, bytes tokenOrigAccount, uint shadowChainID); function getAncestorInfo(uint id) external view returns (bytes account, string name, string symbol, uint8 decimals, uint chainId); function mintToken(address tokenAddress, address to, uint value) external; function burnToken(address tokenAddress, address from, uint value) external; function mapTokenPairType(uint tokenPairID) external view returns (uint8 tokenPairType); // erc1155 function mintNFT(uint tokenCrossType, address tokenAddress, address to, uint[] ids, uint[] values, bytes data) public; function burnNFT(uint tokenCrossType, address tokenAddress, address from, uint[] ids, uint[] values) public; }
contracts/gpk/GpkProxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.24; import "../components/Admin.sol"; import "./GpkStorage.sol"; import "../components/Proxy.sol"; contract GpkProxy is GpkStorage, Admin, Proxy { /** * * MANIPULATIONS * */ /// @notice function for setting or upgrading GpkDelegate address by owner /// @param impl GpkDelegate contract address function upgradeTo(address impl) external onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require(impl != _implementation, "Cannot upgrade to the same implementation"); _implementation = impl; emit Upgraded(impl); } }
contracts/crossApproach/lib/HTLCDebtLib.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; // import "./HTLCTxLib.sol"; import "./CrossTypes.sol"; library HTLCDebtLib { // using SafeMath for uint; // using HTLCTxLib for HTLCTxLib.Data; /** * * STRUCTURES * */ /// @notice struct of debt and asset parameters struct DebtAssetParams { bytes32 uniqueID; /// hash of HTLC random number bytes32 srcSmgID; /// ID of source storeman group bytes32 destSmgID; /// ID of destination storeman group } /** * * EVENTS * **/ /// @notice event of storeman asset transfer /// @param uniqueID random number /// @param srcSmgID ID of source storeman group /// @param destSmgID ID of destination storeman group event TransferAssetLogger(bytes32 indexed uniqueID, bytes32 indexed srcSmgID, bytes32 indexed destSmgID); /// @notice event of storeman debt receive /// @param uniqueID random number /// @param srcSmgID ID of source storeman group /// @param destSmgID ID of destination storeman group event ReceiveDebtLogger(bytes32 indexed uniqueID, bytes32 indexed srcSmgID, bytes32 indexed destSmgID); /** * * MANIPULATIONS * */ /// @notice transfer asset /// @param storageData Cross storage data /// @param params parameters of storeman debt lock function transferAsset(CrossTypes.Data storage storageData, DebtAssetParams memory params) public { if (address(storageData.quota) != address(0)) { storageData.quota.transferAsset(params.srcSmgID, params.destSmgID); } emit TransferAssetLogger(params.uniqueID, params.srcSmgID, params.destSmgID); } /// @notice receive debt /// @param storageData Cross storage data /// @param params parameters of storeman debt lock function receiveDebt(CrossTypes.Data storage storageData, DebtAssetParams memory params) public { if (address(storageData.quota) != address(0)) { storageData.quota.receiveDebt(params.srcSmgID, params.destSmgID); } emit ReceiveDebtLogger(params.uniqueID, params.srcSmgID, params.destSmgID); } }
contracts/lib/PosLib.sol
pragma solidity ^0.4.24; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; library PosLib { using SafeMath for uint; uint public constant DIVISOR = 10000; address constant PRECOMPILE_CONTRACT_ADDR = 0x268; function getEpochId(uint256 blockTime) public view returns (uint256) { bytes32 functionSelector = keccak256("getEpochId(uint256)"); (uint256 result, bool success) = callWith32BytesReturnsUint256( 0x262, functionSelector, bytes32(blockTime) ); require(success, "ASSEMBLY_CALL getEpochId failed"); return result; } function callWith32BytesReturnsUint256( address to, bytes32 functionSelector, bytes32 param1 ) private view returns (uint256 result, bool success) { assembly { let freePtr := mload(0x40) mstore(freePtr, functionSelector) mstore(add(freePtr, 4), param1) // call ERC20 Token contract transfer function success := staticcall(gas, to, freePtr, 36, freePtr, 32) result := mload(freePtr) } } function getPosAvgReturn(uint256 targetSecond) public view returns(uint256 result,bool success) { // bytes32 functionSelector = keccak256("getPosAvgReturn(uint256)"); bytes32 functionSelector = 0x94fee72400000000000000000000000000000000000000000000000000000000; address to = PRECOMPILE_CONTRACT_ADDR; assembly { let freePtr := mload(0x40) mstore(freePtr, functionSelector) mstore(add(freePtr, 4), targetSecond) // call ERC20 Token contract transfer function success := staticcall(gas, to, freePtr,36, freePtr, 32) result := mload(freePtr) } } function testGetHardCap () public view returns(uint256,bool) { return getHardCap(now - 3600 * 24); } function getHardCap (uint256 time) public view returns(uint256,bool) { bytes32 functionSelector = 0x8b19e7b700000000000000000000000000000000000000000000000000000000; address to = PRECOMPILE_CONTRACT_ADDR; uint256 posReturn=0; bool success; assembly { let freePtr := mload(0x40) mstore(freePtr, functionSelector) mstore(add(freePtr, 4), time) success := staticcall(gas, to, freePtr,36, freePtr, 32) posReturn := mload(freePtr) } return (posReturn,success); } // function getMinIncentive1 () public view returns(uint256,uint256) { // return (getMinIncentive(100000 ether,now - 86400 * 4),0); // } // function getMinIncentive2 () public view returns(uint256,uint256) { // return (getMinIncentive(10000000 ether,now - 86400 * 4),0); // } function getMinIncentive (uint256 smgDeposit,uint256 day, uint256 totalDeposit) public view returns(uint256) { uint256 p1; bool success; uint targetSecond = day.mul(3600*24); (p1,success) = getPosAvgReturn(targetSecond); if(!success) { return 0; } uint256 p1Return = smgDeposit.mul(p1).div(DIVISOR).div(365); uint256 hardcap; (hardcap,success) = getHardCap(targetSecond); if(!success) { return 0; } uint256 hardcapReturn = hardcap.mul(1 ether).div(DIVISOR).mul(smgDeposit).div(totalDeposit); return hardcapReturn<=p1Return?hardcapReturn:p1Return; } }
contracts/crossApproach/CrossStorage.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; import "../components/BasicStorage.sol"; import "./lib/CrossTypes.sol"; import "./lib/HTLCTxLib.sol"; import "./lib/RapidityTxLib.sol"; contract CrossStorage is BasicStorage { using HTLCTxLib for HTLCTxLib.Data; using RapidityTxLib for RapidityTxLib.Data; /************************************************************ ** ** VARIABLES ** ************************************************************/ CrossTypes.Data internal storageData; /// @notice locked time(in seconds) uint public lockedTime = uint(3600*36); /// @notice Since storeman group admin receiver address may be changed, system should make sure the new address /// @notice can be used, and the old address can not be used. The solution is add timestamp. /// @notice unit: second uint public smgFeeReceiverTimeout = uint(10*60); enum GroupStatus { none, initial, curveSeted, failed, selected, ready, unregistered, dismissed } }
openzeppelin-eth/contracts/utils/Address.sol
pragma solidity ^0.4.24; /** * Utility library of inline functions on addresses */ library Address { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param account address of the account to check * @return whether the target address is a contract */ function isContract(address account) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } }
contracts/crossApproach/lib/NFTLibV1.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "../../interfaces/IERC1155.sol"; import 'openzeppelin-eth/contracts/token/ERC721/IERC721.sol'; import "./RapidityTxLib.sol"; import "./CrossTypesV1.sol"; import "../../interfaces/ITokenManager.sol"; library NFTLibV1 { using SafeMath for uint; using RapidityTxLib for RapidityTxLib.Data; enum TokenCrossType {ERC20, ERC721, ERC1155} /// @notice struct of Rapidity storeman mint lock parameters struct RapidityUserLockNFTParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint[] tokenIDs; /// NFT token Ids uint[] tokenValues; /// NFT token values uint currentChainID; /// current chain ID uint tokenPairContractFee; /// fee of token pair bytes destUserAccount; /// account of shadow chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity storeman mint lock parameters struct RapiditySmgMintNFTParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint[] tokenIDs; /// NFT token Ids uint[] tokenValues; /// NFT token values bytes extData; /// storeman data address destTokenAccount; /// shadow token account address destUserAccount; /// account of shadow chain, used to receive token } /// @notice struct of Rapidity user burn lock parameters struct RapidityUserBurnNFTParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint[] tokenIDs; /// NFT token Ids uint[] tokenValues; /// NFT token values uint currentChainID; /// current chain ID uint tokenPairContractFee; /// fee of token pair address srcTokenAccount; /// shadow token account bytes destUserAccount; /// account of token destination chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity user burn lock parameters struct RapiditySmgReleaseNFTParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint[] tokenIDs; /// NFT token Ids uint[] tokenValues; /// NFT token values address destTokenAccount; /// original token/coin account address destUserAccount; /// account of token original chain, used to receive token } event UserLockNFT(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, string[] keys, bytes[] values); event UserBurnNFT(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, string[] keys, bytes[] values); event SmgMintNFT(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, string[] keys, bytes[] values); event SmgReleaseNFT(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, string[] keys, bytes[] values); function getTokenScAddrAndContractFee(CrossTypesV1.Data storage storageData, uint tokenPairID, uint tokenPairContractFee, uint currentChainID, uint batchLength) public view returns (address, uint) { ITokenManager tokenManager = storageData.tokenManager; uint fromChainID; uint toChainID; bytes memory fromTokenAccount; bytes memory toTokenAccount; (fromChainID,fromTokenAccount,toChainID,toTokenAccount) = tokenManager.getTokenPairInfo(tokenPairID); require(fromChainID != 0, "Token does not exist"); uint contractFee = tokenPairContractFee; address tokenScAddr; if (currentChainID == fromChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[fromChainID][toChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(fromTokenAccount); } else if (currentChainID == toChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[toChainID][fromChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(toTokenAccount); } else { require(false, "Invalid token pair"); } if (contractFee > 0) { contractFee = contractFee.mul(9 + batchLength).div(10); } return (tokenScAddr, contractFee); } /// @notice mintBridge, user lock token on token original chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for user mint lock token on token original chain function userLockNFT(CrossTypesV1.Data storage storageData, RapidityUserLockNFTParams memory params) public { address tokenScAddr; uint contractFee; (tokenScAddr, contractFee) = getTokenScAddrAndContractFee(storageData, params.tokenPairID, params.tokenPairContractFee, params.currentChainID, params.tokenIDs.length); if (contractFee > 0) { params.smgFeeProxy.transfer(contractFee); } uint left = (msg.value).sub(contractFee); uint8 tokenCrossType = storageData.tokenManager.mapTokenPairType(params.tokenPairID); if (tokenCrossType == uint8(TokenCrossType.ERC721)) { for(uint idx = 0; idx < params.tokenIDs.length; ++idx) { IERC721(tokenScAddr).safeTransferFrom(msg.sender, address(this), params.tokenIDs[idx], ""); } } else if(tokenCrossType == uint8(TokenCrossType.ERC1155)) { IERC1155(tokenScAddr).safeBatchTransferFrom(msg.sender, address(this), params.tokenIDs, params.tokenValues, ""); } else{ require(false, "Invalid NFT type"); } if (left != 0) { (msg.sender).transfer(left); } string[] memory keys = new string[](4); bytes[] memory values = new bytes[](4); keys[0] = "tokenIDs:uint256[]"; values[0] = abi.encode(params.tokenIDs); keys[1] = "tokenValues:uint256[]"; values[1] = abi.encode(params.tokenValues); keys[2] = "userAccount:bytes"; values[2] = params.destUserAccount; keys[3] = "contractFee:uint256"; values[3] = abi.encodePacked(contractFee); emit UserLockNFT(params.smgID, params.tokenPairID, tokenScAddr, keys, values); } /// @notice burnBridge, user lock token on token original chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for user burn lock token on token original chain function userBurnNFT(CrossTypesV1.Data storage storageData, RapidityUserBurnNFTParams memory params) public { address tokenScAddr; uint contractFee; (tokenScAddr, contractFee) = getTokenScAddrAndContractFee(storageData, params.tokenPairID, params.tokenPairContractFee, params.currentChainID, params.tokenIDs.length); ITokenManager tokenManager = storageData.tokenManager; uint8 tokenCrossType = tokenManager.mapTokenPairType(params.tokenPairID); require((tokenCrossType == uint8(TokenCrossType.ERC721) || tokenCrossType == uint8(TokenCrossType.ERC1155)), "Invalid NFT type"); ITokenManager(tokenManager).burnNFT(uint(tokenCrossType), tokenScAddr, msg.sender, params.tokenIDs, params.tokenValues); if (contractFee > 0) { params.smgFeeProxy.transfer(contractFee); } uint left = (msg.value).sub(contractFee); if (left != 0) { (msg.sender).transfer(left); } string[] memory keys = new string[](4); bytes[] memory values = new bytes[](4); keys[0] = "tokenIDs:uint256[]"; values[0] = abi.encode(params.tokenIDs); keys[1] = "tokenValues:uint256[]"; values[1] = abi.encode(params.tokenValues); keys[2] = "userAccount:bytes"; values[2] = params.destUserAccount; keys[3] = "contractFee:uint256"; values[3] = abi.encodePacked(contractFee); emit UserBurnNFT(params.smgID, params.tokenPairID, tokenScAddr, keys, values); } /// @notice mintBridge, storeman mint lock token on token shadow chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for storeman mint lock token on token shadow chain function smgMintNFT(CrossTypesV1.Data storage storageData, RapiditySmgMintNFTParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); ITokenManager tokenManager = storageData.tokenManager; uint8 tokenCrossType = tokenManager.mapTokenPairType(params.tokenPairID); require((tokenCrossType == uint8(TokenCrossType.ERC721) || tokenCrossType == uint8(TokenCrossType.ERC1155)), "Invalid NFT type"); ITokenManager(tokenManager).mintNFT(uint(tokenCrossType), params.destTokenAccount, params.destUserAccount, params.tokenIDs, params.tokenValues, params.extData); string[] memory keys = new string[](5); bytes[] memory values = new bytes[](5); keys[0] = "tokenIDs:uint256[]"; values[0] = abi.encode(params.tokenIDs); keys[1] = "tokenValues:uint256[]"; values[1] = abi.encode(params.tokenValues); keys[2] = "tokenAccount:address"; values[2] = abi.encodePacked(params.destTokenAccount); keys[3] = "userAccount:address"; values[3] = abi.encodePacked(params.destUserAccount); keys[4] = "extData:bytes"; values[4] = params.extData; emit SmgMintNFT(params.uniqueID, params.smgID, params.tokenPairID, keys, values); } /// @notice burnBridge, storeman burn lock token on token shadow chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for storeman burn lock token on token shadow chain function smgReleaseNFT(CrossTypesV1.Data storage storageData, RapiditySmgReleaseNFTParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); uint8 tokenCrossType = storageData.tokenManager.mapTokenPairType(params.tokenPairID); if (tokenCrossType == uint8(TokenCrossType.ERC721)) { for(uint idx = 0; idx < params.tokenIDs.length; ++idx) { IERC721(params.destTokenAccount).safeTransferFrom(address(this), params.destUserAccount, params.tokenIDs[idx], ""); } } else if(tokenCrossType == uint8(TokenCrossType.ERC1155)) { IERC1155(params.destTokenAccount).safeBatchTransferFrom(address(this), params.destUserAccount, params.tokenIDs, params.tokenValues, ""); } else { require(false, "Invalid NFT type"); } string[] memory keys = new string[](4); bytes[] memory values = new bytes[](4); keys[0] = "tokenIDs:uint256[]"; values[0] = abi.encode(params.tokenIDs); keys[1] = "tokenValues:uint256[]"; values[1] = abi.encode(params.tokenValues); keys[2] = "tokenAccount:address"; values[2] = abi.encodePacked(params.destTokenAccount); keys[3] = "userAccount:address"; values[3] = abi.encodePacked(params.destUserAccount); emit SmgReleaseNFT(params.uniqueID, params.smgID, params.tokenPairID, keys, values); } }
contracts/schnorr/SignatureVerifier.sol
pragma solidity ^0.4.24; import "../components/Halt.sol"; import "../interfaces/ISignatureVerifier.sol"; /// @dev for multi curves contract call. interface IBaseSignVerifier { function verify( bytes32 signature, bytes32 groupKeyX, bytes32 groupKeyY, bytes32 randomPointX, bytes32 randomPointY, bytes32 message ) external returns (bool); } contract SignatureVerifier is Halt { /// @dev a map from a uint256 curveId to it's verifier contract address. mapping(uint256 => address) public verifierMap; /// @dev verify is used for check signature. function verify( uint256 curveId, bytes32 signature, bytes32 groupKeyX, bytes32 groupKeyY, bytes32 randomPointX, bytes32 randomPointY, bytes32 message ) external returns (bool) { require(verifierMap[curveId] != address(0), "curveId not correct"); IBaseSignVerifier verifier = IBaseSignVerifier(verifierMap[curveId]); return verifier.verify(signature, groupKeyX, groupKeyY, randomPointX, randomPointY, message); } function register(uint256 curveId, address verifierAddress) external onlyOwner { verifierMap[curveId] = verifierAddress; } }
contracts/metric/lib/MetricLib.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; import "./MetricTypes.sol"; import "../../lib/CommonTool.sol"; import "../../interfaces/IPosLib.sol"; import "../../interfaces/IStoremanGroup.sol"; import "../../interfaces/ICurve.sol"; library MetricLib { using SafeMath for uint; /// @notice function for write slash of R stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param rslshData slash data of R stage /// @param smCount total number of store man function writeRSlsh(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, MetricTypes.RSlshData memory rslshData, uint8 smCount) internal returns (bool, uint8) { require(metricData.mapRSlsh[grpId][hashX][rslshData.sndrIndex].polyDataPln.polyData.length == 0,"Duplicate RSlsh"); require(rslshData.sndrIndex <= smCount, "invalid send index"); require(rslshData.rcvrIndex <= smCount, "invalid receiver index"); require(rslshData.polyCMData.polyCM.length != 0, "polyCM is empty"); require(rslshData.polyDataPln.polyData.length != 0, "polyData is empty"); require(rslshData.becauseSndr, "R because sender is not true"); uint8 smIndex; //smIndex = rslshData.becauseSndr ? rslshData.sndrIndex : rslshData.rcvrIndex; smIndex = rslshData.sndrIndex; metricData.mapRSlsh[grpId][hashX][smIndex] = rslshData; if (checkRProof(metricData, grpId, hashX, smIndex)) { metricData.mapSlshCount[grpId][getEpochId(metricData)][smIndex] = metricData.mapSlshCount[grpId][getEpochId(metricData)][smIndex].add(uint(1)); return (true, smIndex); } else { delete metricData.mapRSlsh[grpId][hashX][smIndex]; return (false, smIndex); } } /// @notice check proof of R stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function checkRProof(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, uint8 smIndex) internal returns (bool) { bool bSig = checkRSig(metricData, grpId, hashX, smIndex); bool bContent = checkRContent(metricData, grpId, hashX, smIndex); return getChkResult(bSig, bContent); } /// @notice check signature of proof in R stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function checkRSig(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, uint8 smIndex) internal returns (bool) { bytes32 h; bytes memory senderPk; MetricTypes.RSlshData rslshData = metricData.mapRSlsh[grpId][hashX][smIndex]; // build h h = sha256(rslshData.polyDataPln.polyData); // build senderpk senderPk = getPkBytesByInx(metricData, grpId, rslshData.sndrIndex); return ckSig(metricData,h, rslshData.polyDataPln.polyDataR, rslshData.polyDataPln.polyDataS, senderPk); } /// @notice check content of proof in R stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function checkRContent(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, uint8 smIndex) internal returns (bool) { uint256 xLeft; uint256 yLeft; uint256 xRight; uint256 yRight; bool success; bytes memory sij; bytes memory rcvrPk; MetricTypes.RSlshData memory rslshData = metricData.mapRSlsh[grpId][hashX][smIndex]; sij = rslshData.polyDataPln.polyData; rcvrPk = getPkBytesByInx(metricData, grpId, rslshData.rcvrIndex); // left point compute by CMG polyCM:= 64*n address curveAddr; curveAddr = IConfig(metricData.config).getCurve(uint8(rslshData.curveType)); (xLeft, yLeft, success) = ICurve(curveAddr).calPolyCommit(rslshData.polyCMData.polyCM, rcvrPk); require(success, 'calPolyCommit fail'); // right point s[i][i]*G uint256 uintSij = CommonTool.bytes2uint(sij, 0, uint16(sij.length)); (xRight, yRight, success) = ICurve(curveAddr).mulG(uintSij); require(success, 'mulG fail'); return ICurve(curveAddr).equalPt(xLeft,yLeft,xRight,yRight); } function getChkResult(bool bSig, bool bContent) internal pure returns (bool) { return !bSig || !bContent; } /// @notice function for write slash of S stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param sslshData slash data of S stage /// @param smCount total number of store man function writeSSlsh(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, MetricTypes.SSlshData sslshData, uint8 smCount) public returns (bool, uint8) { require(metricData.mapSSlsh[grpId][hashX][sslshData.sndrIndex].polyDataPln.polyData.length == 0,"Duplicate SSlsh"); require(sslshData.sndrIndex <= smCount, "invalid send index"); require(sslshData.rcvrIndex <= smCount, "invalid receiver index"); require(sslshData.m.length != 0, "m is empty"); require(sslshData.rpkShare.length != 0, "rpkShare is empty"); require(sslshData.gpkShare.length != 0, "gpkShare is empty"); require(sslshData.polyDataPln.polyData.length != 0, "polyData is empty"); require(sslshData.becauseSndr, "S because sender is not true"); uint8 smIndex; //smIndex = sslshData.becauseSndr ? sslshData.sndrIndex : sslshData.rcvrIndex; smIndex = sslshData.sndrIndex; metricData.mapSSlsh[grpId][hashX][smIndex] = sslshData; if (checkSProof(metricData, grpId, hashX, smIndex)) { metricData.mapSlshCount[grpId][getEpochId(metricData)][smIndex] = metricData.mapSlshCount[grpId][getEpochId(metricData)][smIndex].add(uint(1)); return (true, smIndex); } else { delete metricData.mapSSlsh[grpId][hashX][smIndex]; return (false, smIndex); } } /// @notice check proof of S stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function checkSProof(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, uint8 smIndex) internal returns (bool) { bool bSig = checkSSig(metricData, grpId, hashX, smIndex); bool bContent = checkSContent(metricData, grpId, hashX, smIndex); return getChkResult(bSig, bContent); } /// @notice check signature of proof in S stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function checkSSig(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, uint8 smIndex) internal returns (bool) { bytes32 h; bytes memory senderPk; MetricTypes.SSlshData sslshData = metricData.mapSSlsh[grpId][hashX][smIndex]; // build h h = sha256(sslshData.polyDataPln.polyData); // build senderpk senderPk = getPkBytesByInx(metricData, grpId, sslshData.sndrIndex); return ckSig(metricData, h, sslshData.polyDataPln.polyDataR, sslshData.polyDataPln.polyDataS, senderPk); } function ckSig(MetricTypes.MetricStorageData storage metricData, bytes32 hash, bytes32 r, bytes32 s, bytes pk) internal returns (bool){ address curveAddr; curveAddr = IConfig(metricData.config).getCurve(uint8(CommonTool.CurveType.SK)); return ICurve(curveAddr).checkSig(hash, r, s, pk); } /// @notice check content of proof in S stage /// @param metricData self parameter for lib function /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function checkSContent(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, bytes32 hashX, uint8 smIndex) internal returns (bool) { bool success; uint xLeft; uint yLeft; uint xRight; uint yRight; uint mgpkX; uint mgpkY; MetricTypes.SSlshData memory sslshData = metricData.mapSSlsh[grpId][hashX][smIndex]; // s*G address curveAddr; curveAddr = IConfig(metricData.config).getCurve(uint8(sslshData.curveType)); uint16 ployDataLen = uint16(sslshData.polyDataPln.polyData.length); (xRight, yRight, success) = ICurve(curveAddr).mulG(CommonTool.bytes2uint(sslshData.polyDataPln.polyData, 0,ployDataLen)); require(success, 'mulG fail'); // rpkShare + m * gpkShare (mgpkX, mgpkY, success) = ICurve(curveAddr).mulPk(CommonTool.bytes2uint(sslshData.m, 0, uint16(sslshData.m.length)), CommonTool.bytes2uint(sslshData.gpkShare, 0, 32), CommonTool.bytes2uint(sslshData.gpkShare, 32, 32)); require(success, 'mulPk fail'); (xLeft, yLeft, success) = ICurve(curveAddr).add(CommonTool.bytes2uint(sslshData.rpkShare, 0, 32), CommonTool.bytes2uint(sslshData.rpkShare, 32, 32), mgpkX, mgpkY); require(success, 'add fail'); return ICurve(curveAddr).equalPt(xLeft,yLeft,yLeft,yRight); } /// @notice get public key bytes by stor eman index /// @param metricData self parameter for lib function /// @param grpId group id /// @param smIndex index of store man function getPkBytesByInx(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, uint8 smIndex) internal view returns (bytes) { bytes memory smPk; (, smPk,) = (IStoremanGroup)(metricData.smg).getSelectedSmInfo(grpId, uint(smIndex)); return smPk; } /// @notice get epoch id by now time stamp /// @param metricData self parameter for lib function function getEpochId(MetricTypes.MetricStorageData storage metricData) internal view returns (uint) { return IPosLib(metricData.posLib).getEpochId(now); } /// @notice get total number of store man in special group /// @param metricData self parameter for lib function /// @param grpId group id function getSMCount(MetricTypes.MetricStorageData storage metricData, bytes32 grpId) public view returns (uint8) { IStoremanGroup smgTemp = IStoremanGroup(metricData.smg); return uint8(smgTemp.getSelectedSmNumber(grpId)); } /// @notice get leader address of the group /// @param metricData self parameter for lib function /// @param grpId group id function getLeader(MetricTypes.MetricStorageData storage metricData, bytes32 grpId) public view returns (address) { address leader; IStoremanGroup smgTemp = IStoremanGroup(metricData.smg); (leader,,) = smgTemp.getSelectedSmInfo(grpId, uint(0)); return leader; } /// @notice get work address of the group /// @param metricData self parameter for lib function /// @param grpId group id /// @param smIndex sm index function getWkAddr(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, uint smIndex) public view returns (address) { address wkAddr; IStoremanGroup smgTemp = IStoremanGroup(metricData.smg); (wkAddr,,) = smgTemp.getSelectedSmInfo(grpId, smIndex); return wkAddr; } /// @notice record sm slash /// @param metricData self parameter for lib function /// @param grpId group id /// @param smIndex sm index function recordSmSlash(MetricTypes.MetricStorageData storage metricData, bytes32 grpId, uint smIndex) public view { address wkAddr; IStoremanGroup smgTemp = IStoremanGroup(metricData.smg); wkAddr = getWkAddr(metricData, grpId, smIndex); smgTemp.recordSmSlash(wkAddr); } }
openzeppelin-eth/contracts/token/ERC721/ERC721Metadata.sol
pragma solidity ^0.4.24; import "../../zos-lib/Initializable.sol"; import "./ERC721.sol"; import "./IERC721Metadata.sol"; import "../../introspection/ERC165.sol"; contract ERC721Metadata is Initializable, ERC165, ERC721, IERC721Metadata { // Token name string internal _name; // Token symbol string internal _symbol; // Optional mapping for token URIs mapping(uint256 => string) private _tokenURIs; bytes4 private constant InterfaceId_ERC721Metadata = 0x5b5e139f; /** * 0x5b5e139f === * bytes4(keccak256('name()')) ^ * bytes4(keccak256('symbol()')) ^ * bytes4(keccak256('tokenURI(uint256)')) */ /** * @dev Constructor function */ function initialize(string name, string symbol) public initializer { require(ERC721._hasBeenInitialized()); _name = name; _symbol = symbol; // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(InterfaceId_ERC721Metadata); } function _hasBeenInitialized() internal view returns (bool) { return supportsInterface(InterfaceId_ERC721Metadata); } /** * @dev Gets the token name * @return string representing the token name */ function name() external view returns (string) { return _name; } /** * @dev Gets the token symbol * @return string representing the token symbol */ function symbol() external view returns (string) { return _symbol; } /** * @dev Returns an URI for a given token ID * Throws if the token ID does not exist. May return an empty string. * @param tokenId uint256 ID of the token to query */ function tokenURI(uint256 tokenId) public view returns (string) { require(_exists(tokenId)); return _tokenURIs[tokenId]; } /** * @dev Internal function to set the token URI for a given token * Reverts if the token ID does not exist * @param tokenId uint256 ID of the token to set its URI * @param uri string URI to assign */ function _setTokenURI(uint256 tokenId, string uri) internal { require(_exists(tokenId)); _tokenURIs[tokenId] = uri; } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned by the msg.sender */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); // Clear metadata (if any) if (bytes(_tokenURIs[tokenId]).length != 0) { delete _tokenURIs[tokenId]; } } uint256[50] private ______gap; }
contracts/interfaces/IPosLib.sol
pragma solidity 0.4.26; interface IPosLib { function getEpochId(uint256 blockTime) external view returns (uint256); function getMinIncentive(uint256 smgDeposit, uint256 day, uint256 totalDeposit) external view returns (uint256); }
contracts/metric/lib/MetricTypes.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../../interfaces/IConfig.sol"; import "../../interfaces/IStoremanGroup.sol"; import "../../lib/CommonTool.sol"; library MetricTypes { enum SlshReason {CM, R, RNK, S, SNK} struct PolyCMData { bytes polyCM; bytes32 polyCMR; bytes32 polyCMS; } struct PolyDataPln { bytes polyData; bytes32 polyDataR; bytes32 polyDataS; } struct RSlshData { PolyCMData polyCMData; PolyDataPln polyDataPln; uint8 sndrIndex; uint8 rcvrIndex; bool becauseSndr; CommonTool.CurveType curveType; } struct SSlshData { PolyDataPln polyDataPln; bytes m; // hash(R|| hash(M)) bytes rpkShare; bytes gpkShare; uint8 sndrIndex; uint8 rcvrIndex; bool becauseSndr; CommonTool.CurveType curveType; } struct InctData { uint256 smIndexes; } struct RNWData { uint256 smIndexes; } struct SNWData { uint256 smIndexes; } struct MetricStorageData { /** Incentive data **/ /// groupId -> hashx -> InctData mapping(bytes32 => mapping(bytes32 => InctData)) mapInct; /** R slsh data **/ // groupId -> hashx -> smIndex -> RSlshData mapping(bytes32 => mapping(bytes32 => mapping(uint8 => RSlshData))) mapRSlsh; /** R No Working data **/ // groupId -> hashx -> RNWData mapping(bytes32 => mapping(bytes32 => RNWData)) mapRNW; /** S slsh data **/ // groupId -> hashx -> smIndex -> SSlshData mapping(bytes32 => mapping(bytes32 => mapping(uint8 => SSlshData))) mapSSlsh; /** S No Working data **/ // groupId -> hashx -> SNWData mapping(bytes32 => mapping(bytes32 => SNWData)) mapSNW; /** slsh count statistics **/ /// grpId -> epochId -> smIndex -> slsh count mapping(bytes32 => mapping(uint256 => mapping(uint8 => uint256))) mapSlshCount; /** incentive count statistics **/ /// grpId -> epochId -> smIndex -> incentive count mapping(bytes32 => mapping(uint256 => mapping(uint8 => uint256))) mapInctCount; /// config instance address address config; /// smg instance address address smg; /// posLib address address posLib; } }
contracts/schnorr/Secp256k1.sol
pragma solidity ^0.4.24; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; contract Secp256k1 { using SafeMath for uint256; uint256 constant gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798; uint256 constant gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8; uint256 constant n = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; uint256 constant a = 0; uint256 constant b = 7; function getGx() public pure returns (uint256) { return gx; } function getGy() public pure returns (uint256) { return gy; } function ecadd( uint256 x1, uint256 y1, uint256 x2, uint256 y2 ) public view returns (uint256 retx, uint256 rety) { address to = 0X42; assembly { let freePtr := mload(0x40) mstore(add(freePtr, 0), x1) mstore(add(freePtr, 32), y1) mstore(add(freePtr, 64), x2) mstore(add(freePtr, 96), y2) if iszero(staticcall(gas, to, freePtr, 132, freePtr, 64)) { revert(0, 0) } retx := mload(freePtr) rety := mload(add(freePtr, 32)) } } function ecmul( uint256 xPk, uint256 yPk, uint256 scalar ) public view returns (uint256 x, uint256 y) { address to = 0x43; assembly { let freePtr := mload(0x40) mstore(add(freePtr, 0), scalar) mstore(add(freePtr, 32), xPk) mstore(add(freePtr, 64), yPk) if iszero(staticcall(gas, to, freePtr, 96, freePtr, 64)) { revert(0,0) } x := mload(freePtr) y := mload(add(freePtr, 32)) } } }
contracts/tokenManager/WanToken.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; import '../components/StandardToken.sol'; import '../components/Owned.sol'; contract WanToken is StandardToken, Owned { using SafeMath for uint; /**************************************************************************** ** ** MODIFIERS ** ****************************************************************************/ modifier onlyMeaningfulValue(uint value) { require(value > 0, "Value is null"); _; } /**************************************************************************** ** ** EVENTS ** ****************************************************************************/ /// @notice Logger for token mint /// @dev Logger for token mint /// @param account Whom these token will be minted to /// @param value Amount of ETH/WETH to be minted /// @param totalSupply Total amount of WETH after token mint event TokenMintedLogger( address indexed account, uint indexed value, uint indexed totalSupply ); /// @notice Logger for token burn /// @dev Logger for token burn /// @param account Initiator address /// @param value Amount of WETH to be burnt /// @param totalSupply Total amount of WETH after token burn event TokenBurntLogger( address indexed account, uint indexed value, uint indexed totalSupply ); ///@notice Initialize the TokenManager address ///@dev Initialize the TokenManager address ///@param tokenName The token name to be used ///@param tokenSymbol The token symbol to be used ///@param tokenDecimal The token decimals to be used constructor(string tokenName, string tokenSymbol, uint8 tokenDecimal) public { name = tokenName; symbol = tokenSymbol; decimals = tokenDecimal; } /**************************************************************************** ** ** MANIPULATIONS ** ****************************************************************************/ /// @notice Create token /// @dev Create token /// @param account Address will receive token /// @param value Amount of token to be minted function mint(address account, uint value) external onlyOwner onlyMeaningfulValue(value) { require(account != address(0), "Account is null"); balances[account] = balances[account].add(value); totalSupply = totalSupply.add(value); emit TokenMintedLogger(account, value, totalSupply); } /// @notice Burn token /// @dev Burn token /// @param account Address of whose token will be burnt /// @param value Amount of token to be burnt function burn(address account, uint value) external onlyOwner onlyMeaningfulValue(value) { balances[account] = balances[account].sub(value); totalSupply = totalSupply.sub(value); emit TokenBurntLogger(account, value, totalSupply); } }
contracts/quota/QuotaStorage.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; import "../components/BasicStorage.sol"; contract QuotaStorage is BasicStorage { /// @dev Math operations with safety checks using SafeMath for uint; struct Quota { /// amount of original token to be received, equals to amount of WAN token to be minted uint debt_receivable; /// amount of WAN token to be burnt uint debt_payable; /// amount of original token has been exchanged to the wanchain uint _debt; /// amount of original token to be received, equals to amount of WAN token to be minted uint asset_receivable; /// amount of WAN token to be burnt uint asset_payable; /// amount of original token has been exchanged to the wanchain uint _asset; /// data is active bool _active; } /// @dev the denominator of deposit rate value uint public constant DENOMINATOR = 10000; /// @dev mapping: tokenId => storemanPk => Quota mapping(uint => mapping(bytes32 => Quota)) quotaMap; /// @dev mapping: storemanPk => tokenIndex => tokenId, tokenIndex:0,1,2,3... mapping(bytes32 => mapping(uint => uint)) storemanTokensMap; /// @dev mapping: storemanPk => token count mapping(bytes32 => uint) storemanTokenCountMap; /// @dev mapping: htlcAddress => exist mapping(address => bool) public htlcGroupMap; /// @dev save deposit oracle address (storeman admin or oracle) address public depositOracleAddress; /// @dev save price oracle address address public priceOracleAddress; /// @dev deposit rate use for deposit amount calculate uint public depositRate; /// @dev deposit token's symbol string public depositTokenSymbol; /// @dev token manger contract address address public tokenManagerAddress; /// @dev oracle address for check other chain's debt clean address public debtOracleAddress; /// @dev limit the minimize value of fast cross chain uint public fastCrossMinValue; modifier onlyHtlc() { require(htlcGroupMap[msg.sender], "Not in HTLC group"); _; } }
contracts/lib/CommonTool.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; library CommonTool { enum CurveType {SK, BN} address constant PRECOMPILE_CONTRACT_ADDR = 0x268; function bytes2uint(bytes source, uint16 offset, uint16 length) public pure returns(uint) { uint number = 0; for (uint i = 0; i < length; i++) { number = number + uint8(source[i + offset]) * (2 ** (8 * (length - (i + 1)))); } return number; } function bytesToBytes32(bytes memory source) pure public returns (bytes32 result) { assembly { result := mload(add(source, 32)) } } function cmpBytes(bytes b1, bytes b2) public pure returns(bool) { uint len1 = b1.length; uint len2 = b2.length; // maybe has padding if (len2 >= len1) { for (uint i = 0; i < len2; i++) { if (i < len1) { if (b1[i] != b2[i]) { return false; } } else if (b2[i] != 0x0) { return false; } } return true; } else { return false; } } function enc(bytes32 rbpri, bytes32 iv, uint256 mes, bytes pub) public view returns(bytes, bool success) { bytes32 functionSelector = 0xa1ecea4b00000000000000000000000000000000000000000000000000000000; address to = PRECOMPILE_CONTRACT_ADDR; bytes memory cc = new bytes(6*32); assembly { let freePtr := mload(0x40) mstore(freePtr, functionSelector) mstore(add(freePtr, 4), rbpri) mstore(add(freePtr, 36), iv) mstore(add(freePtr, 68), mes) mstore(add(freePtr, 100), mload(add(pub, 32))) mstore(add(freePtr, 132), mload(add(pub, 64))) // call ERC20 Token contract transfer function success := staticcall(gas,to, freePtr, 164, freePtr, 1024) let loopCnt := 0 loop: jumpi(loopend, eq(loopCnt, 6)) mstore(add(cc,mul(add(loopCnt,1),32)),mload(add(freePtr,mul(loopCnt,32)))) loopCnt := add(loopCnt, 1) jump(loop) loopend: } return (cc,success); } }
contracts/gpk/GpkDelegate.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.24; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; import "../components/Admin.sol"; import "./GpkStorage.sol"; import "./lib/GpkLib.sol"; contract GpkDelegate is GpkStorage, Admin { using SafeMath for uint; /** * * EVENTS * */ /// @notice event for storeman submit poly commit /// @param groupId storeman group id /// @param round group negotiate round /// @param curveIndex signature curve index /// @param storeman storeman address event SetPolyCommitLogger(bytes32 indexed groupId, uint16 indexed round, uint8 indexed curveIndex, address storeman); /// @notice event for storeman submit encoded sij /// @param groupId storeman group id /// @param round group negotiate round /// @param curveIndex signature curve index /// @param src src storeman address /// @param dest dest storeman address event SetEncSijLogger(bytes32 indexed groupId, uint16 indexed round, uint8 indexed curveIndex, address src, address dest); /// @notice event for storeman submit result of checking encSij /// @param groupId storeman group id /// @param round group negotiate round /// @param curveIndex signature curve index /// @param src src storeman address /// @param dest dest storeman address /// @param isValid whether encSij is valid event SetCheckStatusLogger(bytes32 indexed groupId, uint16 indexed round, uint8 indexed curveIndex, address src, address dest, bool isValid); /// @notice event for storeman reveal sij /// @param groupId storeman group id /// @param round group negotiate round /// @param curveIndex signature curve index /// @param src src storeman address /// @param dest dest storeman address event RevealSijLogger(bytes32 indexed groupId, uint16 indexed round, uint8 indexed curveIndex, address src, address dest); /** * * MANIPULATIONS * */ /// @notice function for set smg contract address /// @param cfgAddr cfg contract address /// @param smgAddr smg contract address function setDependence(address cfgAddr, address smgAddr) external onlyOwner { require(cfgAddr != address(0), "Invalid cfg"); cfg = cfgAddr; require(smgAddr != address(0), "Invalid smg"); smg = smgAddr; } /// @notice function for set period /// @param groupId group id /// @param ployCommitPeriod ployCommit period /// @param defaultPeriod default period /// @param negotiatePeriod negotiate period function setPeriod(bytes32 groupId, uint32 ployCommitPeriod, uint32 defaultPeriod, uint32 negotiatePeriod) external onlyAdmin { GpkTypes.Group storage group = groupMap[groupId]; group.ployCommitPeriod = ployCommitPeriod; group.defaultPeriod = defaultPeriod; group.negotiatePeriod = negotiatePeriod; } /// @notice function for storeman submit poly commit /// @param groupId storeman group id /// @param roundIndex group negotiate round /// @param curveIndex singnature curve index /// @param polyCommit poly commit list (17 order in x0,y0,x1,y1... format) function setPolyCommit(bytes32 groupId, uint16 roundIndex, uint8 curveIndex, bytes polyCommit) external { require(polyCommit.length > 0, "Invalid polyCommit"); GpkTypes.Group storage group = groupMap[groupId]; GpkTypes.Round storage round = group.roundMap[roundIndex][curveIndex]; if (group.smNumber == 0) { // init group when the first node submit to start every round GpkLib.initGroup(groupId, group, cfg, smg); } if (round.statusTime == 0) { round.statusTime = now; } checkValid(group, roundIndex, curveIndex, GpkTypes.GpkStatus.PolyCommit, true, false, address(0)); require(round.srcMap[msg.sender].polyCommit.length == 0, "Duplicate"); round.srcMap[msg.sender].polyCommit = polyCommit; round.polyCommitCount++; GpkLib.updateGpk(round, polyCommit); GpkLib.updateGpkShare(group, round, polyCommit); if (round.polyCommitCount >= group.smNumber) { round.status = GpkTypes.GpkStatus.Negotiate; round.statusTime = now; } emit SetPolyCommitLogger(groupId, roundIndex, curveIndex, msg.sender); } /// @notice function for report storeman submit poly commit timeout /// @param groupId storeman group id /// @param curveIndex singnature curve index function polyCommitTimeout(bytes32 groupId, uint8 curveIndex) external { GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, group.round, curveIndex, GpkTypes.GpkStatus.PolyCommit, false, false, address(0)); GpkTypes.Round storage round = group.roundMap[group.round][curveIndex]; uint32 timeout = (group.round == 0) ? group.ployCommitPeriod : group.defaultPeriod; require(now.sub(round.statusTime) > timeout, "Not late"); uint slashCount = 0; for (uint i = 0; (i < group.smNumber) && (slashCount + round.polyCommitCount < group.smNumber); i++) { address src = group.addrMap[i]; if (round.srcMap[src].polyCommit.length == 0) { GpkLib.slash(group, curveIndex, GpkTypes.SlashType.PolyCommitTimeout, src, address(0), false, smg); slashCount++; } } GpkLib.slashMulti(group, curveIndex, smg); } /// @notice function for src storeman submit encSij /// @param groupId storeman group id /// @param roundIndex group negotiate round /// @param curveIndex singnature curve index /// @param dest dest storeman address /// @param encSij encSij function setEncSij(bytes32 groupId, uint16 roundIndex, uint8 curveIndex, address dest, bytes encSij) external { require(encSij.length > 0, "Invalid encSij"); // ephemPublicKey(65) + iv(16) + mac(32) + ciphertext(48) GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, roundIndex, curveIndex, GpkTypes.GpkStatus.Negotiate, true, true, dest); GpkTypes.Round storage round = group.roundMap[roundIndex][curveIndex]; GpkTypes.Dest storage d = round.srcMap[msg.sender].destMap[dest]; require(d.encSij.length == 0, "Duplicate"); d.encSij = encSij; d.setTime = now; emit SetEncSijLogger(groupId, roundIndex, curveIndex, msg.sender, dest); } /// @notice function for dest storeman set check status for encSij /// @param groupId storeman group id /// @param roundIndex group negotiate round /// @param curveIndex singnature curve index /// @param src src storeman address /// @param isValid whether encSij is valid function setCheckStatus(bytes32 groupId, uint16 roundIndex, uint8 curveIndex, address src, bool isValid) external { GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, roundIndex, curveIndex, GpkTypes.GpkStatus.Negotiate, true, true, src); GpkTypes.Round storage round = group.roundMap[roundIndex][curveIndex]; GpkTypes.Src storage s = round.srcMap[src]; GpkTypes.Dest storage d = s.destMap[msg.sender]; require(d.encSij.length != 0, "Not ready"); require(d.checkStatus == GpkTypes.CheckStatus.Init, "Duplicate"); d.checkTime = now; emit SetCheckStatusLogger(groupId, roundIndex, curveIndex, src, msg.sender, isValid); if (isValid) { d.checkStatus = GpkTypes.CheckStatus.Valid; s.checkValidCount++; round.checkValidCount++; if (round.checkValidCount >= group.smNumber ** 2) { round.status = GpkTypes.GpkStatus.Complete; round.statusTime = now; GpkLib.tryComplete(group, smg); } } else { d.checkStatus = GpkTypes.CheckStatus.Invalid; } } /// @notice function for report src storeman submit encSij timeout /// @param groupId storeman group id /// @param curveIndex singnature curve index /// @param src src storeman address function encSijTimeout(bytes32 groupId, uint8 curveIndex, address src) external { GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, group.round, curveIndex, GpkTypes.GpkStatus.Negotiate, true, true, src); GpkTypes.Round storage round = group.roundMap[group.round][curveIndex]; GpkTypes.Dest storage d = round.srcMap[src].destMap[msg.sender]; require(d.encSij.length == 0, "Outdated"); require(now.sub(round.statusTime) > group.defaultPeriod, "Not late"); GpkLib.slash(group, curveIndex, GpkTypes.SlashType.EncSijTimout, src, msg.sender, true, smg); } /// @notice function for src storeman reveal sij /// @param groupId storeman group id /// @param roundIndex group negotiate round /// @param curveIndex singnature curve index /// @param dest dest storeman address /// @param sij sij /// @param ephemPrivateKey ecies ephemPrivateKey function revealSij(bytes32 groupId, uint16 roundIndex, uint8 curveIndex, address dest, uint sij, uint ephemPrivateKey) external { GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, roundIndex, curveIndex, GpkTypes.GpkStatus.Negotiate, true, true, dest); GpkTypes.Round storage round = group.roundMap[roundIndex][curveIndex]; GpkTypes.Src storage src = round.srcMap[msg.sender]; GpkTypes.Dest storage d = src.destMap[dest]; require(d.checkStatus == GpkTypes.CheckStatus.Invalid, "Not need"); d.sij = sij; d.ephemPrivateKey = ephemPrivateKey; emit RevealSijLogger(groupId, roundIndex, curveIndex, msg.sender, dest); if (GpkLib.verifySij(d, group.pkMap[dest], src.polyCommit, round.curve)) { GpkLib.slash(group, curveIndex, GpkTypes.SlashType.CheckInvalid, dest, msg.sender, true, smg); } else { GpkLib.slash(group, curveIndex, GpkTypes.SlashType.SijInvalid, msg.sender, dest, true, smg); } } /// @notice function for report dest storeman check Sij timeout /// @param groupId storeman group id /// @param curveIndex singnature curve index /// @param dest dest storeman address function checkSijTimeout(bytes32 groupId, uint8 curveIndex, address dest) external { GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, group.round, curveIndex, GpkTypes.GpkStatus.Negotiate, true, true, dest); GpkTypes.Round storage round = group.roundMap[group.round][curveIndex]; GpkTypes.Dest storage d = round.srcMap[msg.sender].destMap[dest]; require(d.checkStatus == GpkTypes.CheckStatus.Init, "Checked"); require(d.encSij.length != 0, "Not ready"); require(now.sub(d.setTime) > group.defaultPeriod, "Not late"); GpkLib.slash(group, curveIndex, GpkTypes.SlashType.CheckTimeout, dest, msg.sender, true, smg); } /// @notice function for report srcPk submit sij timeout /// @param groupId storeman group id /// @param curveIndex singnature curve index /// @param src src storeman address function SijTimeout(bytes32 groupId, uint8 curveIndex, address src) external { GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, group.round, curveIndex, GpkTypes.GpkStatus.Negotiate, true, true, src); GpkTypes.Round storage round = group.roundMap[group.round][curveIndex]; GpkTypes.Dest storage d = round.srcMap[src].destMap[msg.sender]; require(d.checkStatus == GpkTypes.CheckStatus.Invalid, "Not need"); require(now.sub(d.checkTime) > group.defaultPeriod, "Not late"); GpkLib.slash(group, curveIndex, GpkTypes.SlashType.SijTimeout, src, msg.sender, true, smg); } /// @notice function for terminate protocol /// @param groupId storeman group id /// @param curveIndex singnature curve index function terminate(bytes32 groupId, uint8 curveIndex) external { GpkTypes.Group storage group = groupMap[groupId]; checkValid(group, group.round, curveIndex, GpkTypes.GpkStatus.Negotiate, false, false, address(0)); GpkTypes.Round storage round = group.roundMap[group.round][curveIndex]; require(now.sub(round.statusTime) > group.negotiatePeriod, "Not late"); for (uint i = 0; i < group.smNumber; i++) { address src = group.addrMap[i]; uint slashPair = uint(group.smNumber).sub(uint(round.srcMap[src].checkValidCount)); for (uint j = 0; (j < group.smNumber) && (slashPair > 0); j++) { address dest = group.addrMap[j]; GpkTypes.Dest storage d = round.srcMap[src].destMap[dest]; if (d.checkStatus != GpkTypes.CheckStatus.Valid) { if (d.encSij.length == 0) { GpkLib.slash(group, curveIndex, GpkTypes.SlashType.EncSijTimout, src, dest, false, smg); GpkLib.slash(group, curveIndex, GpkTypes.SlashType.Connive, dest, src, false, smg); } else if (d.checkStatus == GpkTypes.CheckStatus.Init) { GpkLib.slash(group, curveIndex, GpkTypes.SlashType.Connive, src, dest, false, smg); GpkLib.slash(group, curveIndex, GpkTypes.SlashType.CheckTimeout, dest, src, false, smg); } else { // GpkTypes.CheckStatus.Invalid GpkLib.slash(group, curveIndex, GpkTypes.SlashType.SijTimeout, src, dest, false, smg); GpkLib.slash(group, curveIndex, GpkTypes.SlashType.Connive, dest, src, false, smg); } slashPair--; } } } GpkLib.slashMulti(group, curveIndex, smg); } /// @notice function for check paras /// @param group group /// @param roundIndex group negotiate round /// @param curveIndex singnature curve index /// @param status check group status /// @param checkSender whether check msg.sender /// @param checkStoreman whether check storeman /// @param storeman storeman address function checkValid(GpkTypes.Group storage group, uint16 roundIndex, uint8 curveIndex, GpkTypes.GpkStatus status, bool checkSender, bool checkStoreman, address storeman) private view { require(roundIndex == group.round, "Invalid round"); // must be current round require(curveIndex <= 1, "Invalid curve"); // curve only can be 0 or 1 GpkTypes.Round storage round = group.roundMap[roundIndex][curveIndex]; require((round.status == status) && (round.statusTime > 0), "Invalid status"); if (checkSender) { require(group.pkMap[msg.sender].length > 0, "Invalid sender"); } if (checkStoreman) { require(group.pkMap[storeman].length > 0, "Invalid storeman"); } } function getGroupInfo(bytes32 groupId, int32 roundIndex) external view returns(uint16 queriedRound, address curve1, uint8 curve1Status, uint curve1StatusTime, address curve2, uint8 curve2Status, uint curve2StatusTime) { GpkTypes.Group storage group = groupMap[groupId]; queriedRound = (roundIndex >= 0)? uint16(roundIndex) : group.round; GpkTypes.Round storage round1 = group.roundMap[queriedRound][0]; GpkTypes.Round storage round2 = group.roundMap[queriedRound][1]; return (queriedRound, round1.curve, uint8(round1.status), round1.statusTime, round2.curve, uint8(round2.status), round2.statusTime); } function getPolyCommit(bytes32 groupId, uint16 roundIndex, uint8 curveIndex, address src) external view returns(bytes polyCommit) { GpkTypes.Group storage group = groupMap[groupId]; GpkTypes.Round storage round = group.roundMap[roundIndex][curveIndex]; return round.srcMap[src].polyCommit; } function getSijInfo(bytes32 groupId, uint16 roundIndex, uint8 curveIndex, address src, address dest) external view returns(bytes encSij, uint8 checkStatus, uint setTime, uint checkTime, uint sij, uint ephemPrivateKey) { GpkTypes.Group storage group = groupMap[groupId]; GpkTypes.Round storage round = group.roundMap[roundIndex][curveIndex]; GpkTypes.Dest storage d = round.srcMap[src].destMap[dest]; return (d.encSij, uint8(d.checkStatus), d.setTime, d.checkTime, d.sij, d.ephemPrivateKey); } function getGpkShare(bytes32 groupId, uint16 index) external view returns(bytes gpkShare1, bytes gpkShare2) { GpkTypes.Group storage group = groupMap[groupId]; address src = group.addrMap[index]; mapping(uint8 => GpkTypes.Round) roundMap = groupMap[groupId].roundMap[group.round]; return (roundMap[0].srcMap[src].gpkShare, roundMap[1].srcMap[src].gpkShare); } function getGpk(bytes32 groupId) external view returns(bytes gpk1, bytes gpk2) { GpkTypes.Group storage group = groupMap[groupId]; mapping(uint8 => GpkTypes.Round) roundMap = groupMap[groupId].roundMap[group.round]; return (roundMap[0].gpk, roundMap[1].gpk); } /// @notice fallback function function () public payable { revert("Not support"); } }
openzeppelin-eth/contracts/introspection/IERC165.sol
pragma solidity ^0.4.24; /** * @title IERC165 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md */ interface IERC165 { /** * @notice Query if a contract implements an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @dev Interface identification is specified in ERC-165. This function * uses less than 30,000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
contracts/crossApproach/lib/RapidityLibV2.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./RapidityTxLib.sol"; import "./CrossTypesV1.sol"; import "../../interfaces/ITokenManager.sol"; import "../../interfaces/IRC20Protocol.sol"; import "../../interfaces/ISmgFeeProxy.sol"; library RapidityLibV2 { using SafeMath for uint; using RapidityTxLib for RapidityTxLib.Data; /** * * STRUCTURES * */ /// @notice struct of Rapidity storeman mint lock parameters struct CrossFeeParams { uint contractFee; /// token pair id on cross chain uint agentFee; /// exchange token value } /// @notice struct of Rapidity storeman mint lock parameters struct RapidityUserLockParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint currentChainID; /// current chain ID bytes destUserAccount; /// account of shadow chain, used to receive token } /// @notice struct of Rapidity storeman mint lock parameters struct RapiditySmgMintParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value address destTokenAccount; /// shadow token account address destUserAccount; /// account of shadow chain, used to receive token } /// @notice struct of Rapidity user burn lock parameters struct RapidityUserBurnParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint currentChainID; /// current chain ID uint fee; /// exchange token fee address srcTokenAccount; /// shadow token account bytes destUserAccount; /// account of token destination chain, used to receive token } /// @notice struct of Rapidity user burn lock parameters struct RapiditySmgReleaseParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value address destTokenAccount; /// original token/coin account address destUserAccount; /// account of token original chain, used to receive token } /** * * EVENTS * **/ /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity original token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserLockLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint contractFee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity shadow token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserBurnLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint contractFee, uint fee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param tokenAccount Rapidity shadow token account /// @param userAccount account of original chain, used to receive token event SmgMintLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, address tokenAccount, address userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param tokenAccount Rapidity original token account /// @param userAccount account of original chain, used to receive token event SmgReleaseLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, address tokenAccount, address userAccount); /** * * MANIPULATIONS * */ /// @notice mintBridge, user lock token on token original chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for user mint lock token on token original chain function userLock(CrossTypesV1.Data storage storageData, RapidityUserLockParams memory params) public { uint fromChainID; uint toChainID; bytes memory fromTokenAccount; (fromChainID,fromTokenAccount,toChainID) = storageData.tokenManager.getTokenPairInfoSlim(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); if (address(storageData.quota) != address(0)) { storageData.quota.userLock(params.tokenPairID, params.smgID, params.value); } uint contractFee = storageData.mapContractFee[fromChainID][toChainID]; if (contractFee > 0) { if (storageData.smgFeeProxy == address(0)) { storageData.mapStoremanFee[bytes32(0)] = storageData.mapStoremanFee[bytes32(0)].add(contractFee); } else { (storageData.smgFeeProxy).transfer(contractFee); } } address tokenScAddr = CrossTypesV1.bytesToAddress(fromTokenAccount); uint left; if (tokenScAddr == address(0)) { left = (msg.value).sub(params.value).sub(contractFee); } else { left = (msg.value).sub(contractFee); require(CrossTypesV1.transferFrom(tokenScAddr, msg.sender, this, params.value), "Lock token failed"); } if (left != 0) { (msg.sender).transfer(left); } emit UserLockLogger(params.smgID, params.tokenPairID, tokenScAddr, params.value, contractFee, params.destUserAccount); } /// @notice burnBridge, user lock token on token original chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for user burn lock token on token original chain function userBurn(CrossTypesV1.Data storage storageData, RapidityUserBurnParams memory params) public { ITokenManager tokenManager = storageData.tokenManager; uint fromChainID; uint toChainID; bytes memory fromTokenAccount; bytes memory toTokenAccount; (fromChainID,fromTokenAccount,toChainID,toTokenAccount) = tokenManager.getTokenPairInfo(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); uint256 contractFee; address tokenScAddr; if (params.currentChainID == toChainID) { contractFee = storageData.mapContractFee[toChainID][fromChainID]; tokenScAddr = CrossTypesV1.bytesToAddress(toTokenAccount); } else if (params.currentChainID == fromChainID) { contractFee = storageData.mapContractFee[fromChainID][toChainID]; tokenScAddr = CrossTypesV1.bytesToAddress(fromTokenAccount); } else { require(false, "Invalid token pair"); } require(params.srcTokenAccount == tokenScAddr, "invalid token account"); if (address(storageData.quota) != address(0)) { storageData.quota.userBurn(params.tokenPairID, params.smgID, params.value); } require(burnShadowToken(tokenManager, tokenScAddr, msg.sender, params.value), "burn failed"); if (contractFee > 0) { if (storageData.smgFeeProxy == address(0)) { storageData.mapStoremanFee[bytes32(0)] = storageData.mapStoremanFee[bytes32(0)].add(contractFee); } else { (storageData.smgFeeProxy).transfer(contractFee); } } uint left = (msg.value).sub(contractFee); // uint left = (msg.value).sub(contractFee); if (left != 0) { (msg.sender).transfer(left); } emit UserBurnLogger(params.smgID, params.tokenPairID, tokenScAddr, params.value, contractFee, params.fee, params.destUserAccount); } /// @notice mintBridge, storeman mint lock token on token shadow chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for storeman mint lock token on token shadow chain function smgMint(CrossTypesV1.Data storage storageData, RapiditySmgMintParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); if (address(storageData.quota) != address(0)) { storageData.quota.smgMint(params.tokenPairID, params.smgID, params.value); } require(mintShadowToken(storageData.tokenManager, params.destTokenAccount, params.destUserAccount, params.value), "mint failed"); emit SmgMintLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.destTokenAccount, params.destUserAccount); } /// @notice burnBridge, storeman burn lock token on token shadow chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for storeman burn lock token on token shadow chain function smgRelease(CrossTypesV1.Data storage storageData, RapiditySmgReleaseParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); if (address(storageData.quota) != address(0)) { storageData.quota.smgRelease(params.tokenPairID, params.smgID, params.value); } if (params.destTokenAccount == address(0)) { (params.destUserAccount).transfer(params.value); } else { require(CrossTypesV1.transfer(params.destTokenAccount, params.destUserAccount, params.value), "Transfer token failed"); } emit SmgReleaseLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.destTokenAccount, params.destUserAccount); } function burnShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).burnToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.sub(value); } function mintShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).mintToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.add(value); } }
contracts/interfaces/IMappingToken.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; interface IMappingToken { function changeOwner(address _newOwner) external; function acceptOwnership() external; function transferOwner(address) external; function name() external view returns (string); function symbol() external view returns (string); function decimals() external view returns (uint8); function mint(address, uint) external; function burn(address, uint) external; function update(string, string) external; }
contracts/oracle/OracleDelegate.sol
pragma solidity 0.4.26; /** * Math operations with safety checks */ import "../components/Owned.sol"; import "./OracleStorage.sol"; contract OracleDelegate is OracleStorage, Owned { /** * * EVENTS * */ event SetAdmin(address addr); event UpdatePrice(bytes32[] keys, uint[] prices); event SetDebtClean(bytes32 indexed id, bool isDebtClean); event SetStoremanGroupConfig(bytes32 indexed id, uint8 status, uint deposit, uint[2] chain, uint[2] curve, bytes gpk1, bytes gpk2, uint startTime, uint endTime); event SetStoremanGroupStatus(bytes32 indexed id, uint8 status); event UpdateDeposit(bytes32 indexed id, uint deposit); /** * * MODIFIERS * */ modifier onlyAdmin() { require((msg.sender == admin) || (msg.sender == owner), "not admin"); _; } /** * * MANIPULATIONS * */ function updatePrice( bytes32[] keys, uint[] prices ) external onlyAdmin { require(keys.length == prices.length, "length not same"); for (uint256 i = 0; i < keys.length; i++) { mapPrices[keys[i]] = prices[i]; } emit UpdatePrice(keys, prices); } function updateDeposit( bytes32 smgID, uint amount ) external onlyAdmin { mapStoremanGroupConfig[smgID].deposit = amount; emit UpdateDeposit(smgID, amount); } function setStoremanGroupStatus( bytes32 id, uint8 status ) external onlyAdmin { mapStoremanGroupConfig[id].status = status; emit SetStoremanGroupStatus(id, status); } function setStoremanGroupConfig( bytes32 id, uint8 status, uint deposit, uint[2] chain, uint[2] curve, bytes gpk1, bytes gpk2, uint startTime, uint endTime ) external onlyAdmin { mapStoremanGroupConfig[id].deposit = deposit; mapStoremanGroupConfig[id].status = status; mapStoremanGroupConfig[id].chain[0] = chain[0]; mapStoremanGroupConfig[id].chain[1] = chain[1]; mapStoremanGroupConfig[id].curve[0] = curve[0]; mapStoremanGroupConfig[id].curve[1] = curve[1]; mapStoremanGroupConfig[id].gpk1 = gpk1; mapStoremanGroupConfig[id].gpk2 = gpk2; mapStoremanGroupConfig[id].startTime = startTime; mapStoremanGroupConfig[id].endTime = endTime; emit SetStoremanGroupConfig(id, status, deposit, chain, curve, gpk1, gpk2, startTime, endTime); } function setDebtClean( bytes32 storemanGroupId, bool isClean ) external onlyAdmin { mapStoremanGroupConfig[storemanGroupId].isDebtClean = isClean; emit SetDebtClean(storemanGroupId, isClean); } function setAdmin( address addr ) external onlyOwner { admin = addr; emit SetAdmin(addr); } function getValue(bytes32 key) external view returns (uint) { return mapPrices[key]; } function getValues(bytes32[] keys) external view returns (uint[] values) { values = new uint[](keys.length); for(uint256 i = 0; i < keys.length; i++) { values[i] = mapPrices[keys[i]]; } } function getDeposit(bytes32 smgID) external view returns (uint) { return mapStoremanGroupConfig[smgID].deposit; } function getStoremanGroupConfig( bytes32 id ) external view returns(bytes32 groupId, uint8 status, uint deposit, uint chain1, uint chain2, uint curve1, uint curve2, bytes gpk1, bytes gpk2, uint startTime, uint endTime) { groupId = id; status = mapStoremanGroupConfig[id].status; deposit = mapStoremanGroupConfig[id].deposit; chain1 = mapStoremanGroupConfig[id].chain[0]; chain2 = mapStoremanGroupConfig[id].chain[1]; curve1 = mapStoremanGroupConfig[id].curve[0]; curve2 = mapStoremanGroupConfig[id].curve[1]; gpk1 = mapStoremanGroupConfig[id].gpk1; gpk2 = mapStoremanGroupConfig[id].gpk2; startTime = mapStoremanGroupConfig[id].startTime; endTime = mapStoremanGroupConfig[id].endTime; } function getStoremanGroupStatus(bytes32 id) public view returns(uint8 status, uint startTime, uint endTime) { status = mapStoremanGroupConfig[id].status; startTime = mapStoremanGroupConfig[id].startTime; endTime = mapStoremanGroupConfig[id].endTime; } function isDebtClean( bytes32 storemanGroupId ) external view returns (bool) { return mapStoremanGroupConfig[storemanGroupId].isDebtClean; } }
contracts/schnorr/Secp256k1SchnorrVerifier.sol
pragma solidity ^0.4.24; import "./Secp256k1.sol"; contract Secp256k1SchnorrVerifier is Secp256k1 { struct Point { uint256 x; uint256 y; } struct Verification { Point groupKey; Point randomPoint; uint256 signature; bytes32 message; uint256 _hash; Point _left; Point _right; } function h(bytes32 m, uint256 a, uint256 b) public pure returns (uint256) { return uint256(sha256(abi.encodePacked(m, uint8(0x04), a, b))); } // function cmul(Point p, uint256 scalar) public pure returns (uint256, uint256) { function cmul(uint256 x, uint256 y, uint256 scalar) public view returns (uint256, uint256) { return ecmul(x, y, scalar); } function sg(uint256 sig_s) public view returns (uint256, uint256) { return ecmul(getGx(), getGy(), sig_s); } // function cadd(Point a, Point b) public pure returns (uint256, uint256) { function cadd(uint256 ax, uint256 ay, uint256 bx, uint256 by) public view returns (uint256, uint256) { return ecadd(ax, ay, bx, by); } function verify(bytes32 signature, bytes32 groupKeyX, bytes32 groupKeyY, bytes32 randomPointX, bytes32 randomPointY, bytes32 message) public view returns(bool) { bool flag = false; Verification memory state; state.signature = uint256(signature); state.groupKey.x = uint256(groupKeyX); state.groupKey.y = uint256(groupKeyY); state.randomPoint.x = uint256(randomPointX); state.randomPoint.y = uint256(randomPointY); state.message = message; state._hash = h(state.message, state.randomPoint.x, state.randomPoint.y); (state._left.x, state._left.y) = sg(state.signature); Point memory rightPart; (rightPart.x, rightPart.y) = cmul(state.groupKey.x, state.groupKey.y, state._hash); (state._right.x, state._right.y) = cadd(state.randomPoint.x, state.randomPoint.y, rightPart.x, rightPart.y); flag = state._left.x == state._right.x && state._left.y == state._right.y; return flag; } }
contracts/gpk/lib/GpkTypes.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.24; library GpkTypes { struct Group { bytes32 groupId; uint16 round; uint32 ployCommitPeriod; uint32 defaultPeriod; uint32 negotiatePeriod; /// round -> curveIndex -> Round mapping(uint16 => mapping(uint8 => Round)) roundMap; uint16 smNumber; /// index -> txAddress mapping(uint => address) addrMap; /// txAddress -> slectedIndex mapping(address => uint) indexMap; /// txAddress -> pk mapping(address => bytes) pkMap; } struct Round { address curve; GpkStatus status; uint16 polyCommitCount; uint32 checkValidCount; uint16 slashCount; uint statusTime; bytes gpk; /// txAddress -> Src mapping(address => Src) srcMap; } enum GpkStatus {PolyCommit, Negotiate, Complete, Close} struct Src { bytes polyCommit; bytes gpkShare; /// txAddress -> Dest mapping(address => Dest) destMap; uint16 checkValidCount; SlashType slashType; } struct Dest { CheckStatus checkStatus; uint setTime; uint checkTime; uint sij; uint ephemPrivateKey; bytes encSij; } enum CheckStatus {Init, Valid, Invalid} enum SlashType {None, PolyCommitTimeout, EncSijTimout, CheckTimeout, SijTimeout, SijInvalid, CheckInvalid, Connive} }
contracts/interfaces/IWrappedNFT721.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; interface IWrappedNFT721 { function changeOwner(address _newOwner) external; function acceptOwnership() external; function transferOwner(address) external; function name() external view returns (string); function symbol() external view returns (string); function decimals() external view returns (uint8); function burn(address, uint) external; function update(string, string) external; function mint(address, uint, bytes) external; function burnBatch(address , uint256[]) public; function mintBatch(address , uint256[] , bytes) public; }
contracts/components/WRC20Protocol.sol
pragma solidity 0.4.26; contract WRC20Protocol { /* This is a slight change to the ERC20 base standard. function totalSupply() constant returns (uint supply); is replaced with: uint public totalSupply; This automatically creates a getter function for the totalSupply. This is moved to the base contract since public getter functions are not currently recognised as an implementation of the matching abstract function by the compiler. */ /************************************** ** ** VARIABLES ** **************************************/ string public name; string public symbol; uint8 public decimals; mapping (address => uint) balances; mapping (address => mapping (address => uint)) allowed; /// total amount of tokens uint public totalSupply; /// @param _owner The address from which the balance will be retrieved /// @return The balance function balanceOf(address _owner) public view returns (uint balance); /// @notice send `_value` token to `_to` from `msg.sender` /// @param _to The address of the recipient /// @param _value The amount of token to be transferred /// @return Whether the transfer was successful or not function transfer(address _to, uint _value) public returns (bool success); /// @notice send `_value` token to `_to` from `_from` on the condition it is approved by `_from` /// @param _from The address of the sender /// @param _to The address of the recipient /// @param _value The amount of token to be transferred /// @return Whether the transfer was successful or not function transferFrom(address _from, address _to, uint _value) public returns (bool success); /// @notice `msg.sender` approves `_spender` to spend `_value` tokens /// @param _spender The address of the account able to transfer the tokens /// @param _value The amount of tokens to be approved for transfer /// @return Whether the approval was successful or not function approve(address _spender, uint _value) public returns (bool success); /// @param _owner The address of the account owning tokens /// @param _spender The address of the account able to transfer the tokens /// @return Amount of remaining tokens allowed to spent function allowance(address _owner, address _spender) public view returns (uint remaining); event Transfer(address indexed _from, address indexed _to, uint _value); event Approval(address indexed _owner, address indexed _spender, uint _value); }
contracts/crossApproach/lib/CrossTypesV1.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; import "../../interfaces/IRC20Protocol.sol"; import "../../interfaces/IQuota.sol"; import "../../interfaces/IStoremanGroup.sol"; import "../../interfaces/ITokenManager.sol"; import "../../interfaces/ISignatureVerifier.sol"; import "./HTLCTxLib.sol"; import "./RapidityTxLib.sol"; library CrossTypesV1 { using SafeMath for uint; /** * * STRUCTURES * */ struct Data { /// map of the htlc transaction info HTLCTxLib.Data htlcTxData; /// map of the rapidity transaction info RapidityTxLib.Data rapidityTxData; /// quota data of storeman group IQuota quota; /// token manager instance interface ITokenManager tokenManager; /// storemanGroup admin instance interface IStoremanGroup smgAdminProxy; /// storemanGroup fee admin instance address address smgFeeProxy; ISignatureVerifier sigVerifier; /// @notice transaction fee, smgID => fee mapping(bytes32 => uint) mapStoremanFee; /// @notice transaction fee, origChainID => shadowChainID => fee mapping(uint => mapping(uint =>uint)) mapContractFee; /// @notice transaction fee, origChainID => shadowChainID => fee mapping(uint => mapping(uint =>uint)) mapAgentFee; } /** * * MANIPULATIONS * */ // /// @notice convert bytes32 to address // /// @param b bytes32 // function bytes32ToAddress(bytes32 b) internal pure returns (address) { // return address(uint160(bytes20(b))); // high // // return address(uint160(uint256(b))); // low // } /// @notice convert bytes to address /// @param b bytes function bytesToAddress(bytes b) internal pure returns (address addr) { assembly { addr := mload(add(b,20)) } } function transfer(address tokenScAddr, address to, uint value) internal returns(bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenScAddr).balanceOf(to); // IRC20Protocol(tokenScAddr).transfer(to, value); tokenScAddr.call(bytes4(keccak256("transfer(address,uint256)")), to, value); afterBalance = IRC20Protocol(tokenScAddr).balanceOf(to); return afterBalance == beforeBalance.add(value); } function transferFrom(address tokenScAddr, address from, address to, uint value) internal returns(bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenScAddr).balanceOf(to); // IRC20Protocol(tokenScAddr).transferFrom(from, to, value); tokenScAddr.call(bytes4(keccak256("transferFrom(address,address,uint256)")), from, to, value); afterBalance = IRC20Protocol(tokenScAddr).balanceOf(to); return afterBalance == beforeBalance.add(value); } }
contracts/interfaces/IQuota.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; interface IQuota { function userLock(uint tokenId, bytes32 storemanGroupId, uint value) external; function userBurn(uint tokenId, bytes32 storemanGroupId, uint value) external; function smgRelease(uint tokenId, bytes32 storemanGroupId, uint value) external; function smgMint(uint tokenId, bytes32 storemanGroupId, uint value) external; function upgrade(bytes32 storemanGroupId) external; function transferAsset(bytes32 srcStoremanGroupId, bytes32 dstStoremanGroupId) external; function receiveDebt(bytes32 srcStoremanGroupId, bytes32 dstStoremanGroupId) external; function getUserMintQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint); function getSmgMintQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint); function getUserBurnQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint); function getSmgBurnQuota(uint tokenId, bytes32 storemanGroupId) external view returns (uint); function getAsset(uint tokenId, bytes32 storemanGroupId) external view returns (uint asset, uint asset_receivable, uint asset_payable); function getDebt(uint tokenId, bytes32 storemanGroupId) external view returns (uint debt, uint debt_receivable, uint debt_payable); function isDebtClean(bytes32 storemanGroupId) external view returns (bool); }
contracts/storemanGroupAdmin/ListGroup.sol
pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "../components/Admin.sol"; import "./StoremanUtil.sol"; contract ListGroup is Admin { struct Group { bytes32 groupId; uint startTime; uint endTime; } Group[] groups; address public smg; address public posAddr; mapping(uint=>uint) epochDeposit; mapping(address=>mapping(address=>bytes32)) delegateQuitGroupId; mapping(address=>mapping(address=>bytes32)) delegateQuitNextGroupId; mapping(address=>mapping(address=>bytes32)) partQuitGroupId; mapping(address=>mapping(address=>bytes32)) partQuitNextGroupId; constructor(address _smg, address _pos) public { smg = _smg; posAddr = _pos; } function setDelegateQuitGroupId(address wkAddr, address deAddr, bytes32 groupId, bytes32 nextGroupId)external { require(smg == msg.sender, "not allow"); delegateQuitGroupId[wkAddr][deAddr] = groupId; delegateQuitNextGroupId[wkAddr][deAddr] = nextGroupId; } function setPartQuitGroupId(address wkAddr, address pnAddr, bytes32 groupId, bytes32 nextGroupId) external { require(smg == msg.sender, "not allow"); partQuitGroupId[wkAddr][pnAddr] = groupId; partQuitNextGroupId[wkAddr][pnAddr] = nextGroupId; } function getDelegateQuitGroupId(address wkAddr, address deAddr) external view returns (bytes32 groupId, bytes32 nextGroupId){ return (delegateQuitGroupId[wkAddr][deAddr], delegateQuitNextGroupId[wkAddr][deAddr]); } function getPartQuitGroupId(address wkAddr, address pnAddr) external view returns (bytes32 groupId, bytes32 nextGroupId){ return (partQuitGroupId[wkAddr][pnAddr], partQuitNextGroupId[wkAddr][pnAddr]); } function addActiveGroup(bytes32 groupId, uint startTime, uint endTime) external { require(smg == msg.sender, "not allow"); for(uint i=0; i<groups.length; i++){ require(groups[i].groupId != groupId,"existed"); } Group memory one = Group(groupId, startTime, endTime); groups.push(one); } function setTotalDeposit(uint day, uint value) external { require(smg == msg.sender, "not allow"); epochDeposit[day] = value; } function getTotalDeposit(uint day) external view returns(uint) { return epochDeposit[day]; } function getGroups() external view returns (Group[]) { return groups; } function cleanExpiredGroup() external { for(uint i=groups.length; i>0; i--) { if(groups[i-1].endTime < now){ // expired. if(i < groups.length){ groups[i-1]= groups[groups.length-1]; } groups.length--; } } } function getActiveGroupIds(uint epochId) external view returns (bytes32[]) { bytes32[] memory activeGroups = new bytes32[](groups.length); uint activeCount; for(uint i=groups.length; i>0; i--) { if(StoremanUtil.getDaybyTime(posAddr, groups[i-1].startTime) <= epochId){ if(StoremanUtil.getDaybyTime(posAddr, groups[i-1].endTime) > epochId){ // not expired. activeGroups[activeCount] = groups[i-1].groupId; activeCount++; } } } bytes32[] memory ret = new bytes32[](activeCount); for(uint k; k<activeCount; k++) { ret[k] = activeGroups[k]; } return ret; } }
contracts/crossApproach/CrossDelegateXinFin.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./CrossDelegateV4.sol"; contract CrossDelegateXinFin is CrossDelegateV4 { function onXRC721Received(address operator, address from, uint256 tokenId, bytes data) external pure returns (bytes4) { return this.onXRC721Received.selector; } function onXRC1155Received(address _operator, address _from, uint256 _id, uint256 _value, bytes _data) external pure returns(bytes4) { return this.onXRC1155Received.selector; } function onXRC1155BatchReceived(address _operator, address _from, uint256[] _ids, uint256[] _values, bytes _data) external pure returns(bytes4) { return this.onXRC1155BatchReceived.selector; } }
contracts/tokenManager/TokenManagerDelegate.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; pragma experimental ABIEncoderV2; /** * Math operations with safety checks */ import "../interfaces/IMappingToken.sol"; import "../components/Admin.sol"; import "./TokenManagerStorage.sol"; import "./MappingToken.sol"; contract TokenManagerDelegate is TokenManagerStorage, Admin { using SafeMath for uint; /************************************************************ ** ** EVENTS ** ************************************************************/ event AddToken(address tokenAddress, string name, string symbol, uint8 decimals); event AddTokenPair(uint indexed id, uint fromChainID, bytes fromAccount, uint toChainID, bytes toAccount); event UpdateTokenPair(uint indexed id, AncestorInfo aInfo, uint fromChainID, bytes fromAccount, uint toChainID, bytes toAccount); event RemoveTokenPair(uint indexed id); event UpdateToken(address tokenAddress, string name, string symbol); /** * * MODIFIERS * */ modifier onlyNotExistID(uint id) { require(mapTokenPairInfo[id].fromChainID == 0, "token exist"); _; } modifier onlyExistID(uint id) { require(mapTokenPairInfo[id].fromChainID > 0, "token not exist"); _; } /** * * MANIPULATIONS * */ function bytesToAddress(bytes b) internal pure returns (address addr) { assembly { addr := mload(add(b,20)) } } function mintToken( address tokenAddress, address to, uint value ) external onlyAdmin { IMappingToken(tokenAddress).mint(to, value); } function burnToken( address tokenAddress, address from, uint value ) external onlyAdmin { IMappingToken(tokenAddress).burn(from, value); } function addToken( string name, string symbol, uint8 decimals ) external onlyOwner { address tokenAddress = new MappingToken(name, symbol, decimals); emit AddToken(tokenAddress, name, symbol, decimals); } function addTokenPair( uint id, AncestorInfo aInfo, uint fromChainID, bytes fromAccount, uint toChainID, bytes toAccount ) public onlyOwner onlyNotExistID(id) { // create a new record mapTokenPairInfo[id].fromChainID = fromChainID; mapTokenPairInfo[id].fromAccount = fromAccount; mapTokenPairInfo[id].toChainID = toChainID; mapTokenPairInfo[id].toAccount = toAccount; mapTokenPairInfo[id].aInfo.account = aInfo.account; mapTokenPairInfo[id].aInfo.name = aInfo.name; mapTokenPairInfo[id].aInfo.symbol = aInfo.symbol; mapTokenPairInfo[id].aInfo.decimals = aInfo.decimals; mapTokenPairInfo[id].aInfo.chainID = aInfo.chainID; mapTokenPairIndex[totalTokenPairs] = id; totalTokenPairs = totalTokenPairs.add(1); // fire event emit AddTokenPair(id, fromChainID, fromAccount, toChainID, toAccount); } function updateTokenPair( uint id, AncestorInfo aInfo, uint fromChainID, bytes fromAccount, uint toChainID, bytes toAccount ) public onlyOwner onlyExistID(id) { mapTokenPairInfo[id].aInfo.account = aInfo.account; mapTokenPairInfo[id].aInfo.name = aInfo.name; mapTokenPairInfo[id].aInfo.symbol = aInfo.symbol; mapTokenPairInfo[id].aInfo.decimals = aInfo.decimals; mapTokenPairInfo[id].aInfo.chainID = aInfo.chainID; mapTokenPairInfo[id].fromChainID = fromChainID; mapTokenPairInfo[id].fromAccount = fromAccount; mapTokenPairInfo[id].toChainID = toChainID; mapTokenPairInfo[id].toAccount = toAccount; emit UpdateTokenPair(id, aInfo, fromChainID, fromAccount, toChainID, toAccount); } function removeTokenPair( uint id ) external onlyOwner onlyExistID(id) { for(uint i=0; i<totalTokenPairs; i++) { if (id == mapTokenPairIndex[i]) { if (i != totalTokenPairs - 1) { mapTokenPairIndex[i] = mapTokenPairIndex[totalTokenPairs - 1]; } delete mapTokenPairIndex[totalTokenPairs - 1]; totalTokenPairs--; delete mapTokenPairInfo[id]; emit RemoveTokenPair(id); return; } } } function updateToken(address tokenAddress, string name, string symbol) external onlyOwner { IMappingToken(tokenAddress).update(name, symbol); emit UpdateToken(tokenAddress, name, symbol); } function changeTokenOwner(address tokenAddress, address _newOwner) external onlyOwner { IMappingToken(tokenAddress).changeOwner(_newOwner); } function acceptTokenOwnership(address tokenAddress) external { IMappingToken(tokenAddress).acceptOwnership(); } function transferTokenOwner(address tokenAddress, address _newOwner) external onlyOwner { IMappingToken(tokenAddress).transferOwner(_newOwner); } function getTokenPairInfo( uint id ) external view returns (uint fromChainID, bytes fromAccount, uint toChainID, bytes toAccount) { fromChainID = mapTokenPairInfo[id].fromChainID; fromAccount = mapTokenPairInfo[id].fromAccount; toChainID = mapTokenPairInfo[id].toChainID; toAccount = mapTokenPairInfo[id].toAccount; } function getTokenPairInfoSlim( uint id ) external view returns (uint fromChainID, bytes fromAccount, uint toChainID) { fromChainID = mapTokenPairInfo[id].fromChainID; fromAccount = mapTokenPairInfo[id].fromAccount; toChainID = mapTokenPairInfo[id].toChainID; } function getTokenInfo(uint id) external view returns (address addr, string name, string symbol, uint8 decimals) { if (mapTokenPairInfo[id].fromChainID == 0) { name = ''; symbol = ''; decimals = 0; addr = address(0); } else { address instance = bytesToAddress(mapTokenPairInfo[id].toAccount); name = IMappingToken(instance).name(); symbol = IMappingToken(instance).symbol(); decimals = IMappingToken(instance).decimals(); addr = instance; } } function getAncestorInfo(uint id) external view returns (bytes account, string name, string symbol, uint8 decimals, uint chainId) { account = mapTokenPairInfo[id].aInfo.account; name = mapTokenPairInfo[id].aInfo.name; symbol = mapTokenPairInfo[id].aInfo.symbol; decimals = mapTokenPairInfo[id].aInfo.decimals; chainId = mapTokenPairInfo[id].aInfo.chainID; } function getAncestorSymbol(uint id) external view returns (string symbol, uint8 decimals) { symbol = mapTokenPairInfo[id].aInfo.symbol; decimals = mapTokenPairInfo[id].aInfo.decimals; } function getAncestorChainID(uint id) external view returns (uint chainID) { chainID = mapTokenPairInfo[id].aInfo.chainID; } // function getTokenPairsFullFields() // external // view // returns (TokenPairInfoFull[] tokenPairs) // { // tokenPairs = new TokenPairInfoFull[](totalTokenPairs); // for (uint i = 0; i < totalTokenPairs; i++) { // uint theId = mapTokenPairIndex[i]; // tokenPairs[i].aInfo = mapTokenPairInfo[theId].aInfo; // tokenPairs[i].fromChainID = mapTokenPairInfo[theId].fromChainID; // tokenPairs[i].fromAccount = mapTokenPairInfo[theId].fromAccount; // tokenPairs[i].toChainID = mapTokenPairInfo[theId].toChainID; // tokenPairs[i].toAccount = mapTokenPairInfo[theId].toAccount; // tokenPairs[i].id = theId; // } // return tokenPairs; // } // function getTokenPairsByChainID2(uint chainID1, uint chainID2) // external // view // returns (TokenPairInfoFull[] tokenPairs) // { // uint cnt = 0; // uint i = 0; // uint theId = 0; // uint[] memory id_valid = new uint[](totalTokenPairs); // for (; i < totalTokenPairs; i++ ) { // theId = mapTokenPairIndex[i]; // if ((mapTokenPairInfo[theId].fromChainID == chainID1) && (mapTokenPairInfo[theId].toChainID == chainID2) || // (mapTokenPairInfo[theId].toChainID == chainID1) && (mapTokenPairInfo[theId].fromChainID == chainID2)) { // id_valid[cnt] = theId; // cnt ++; // } // } // tokenPairs = new TokenPairInfoFull[](cnt); // for (i = 0; i < cnt; i++) { // theId = id_valid[i]; // tokenPairs[i].aInfo = mapTokenPairInfo[theId].aInfo; // tokenPairs[i].fromChainID = mapTokenPairInfo[theId].fromChainID; // tokenPairs[i].fromAccount = mapTokenPairInfo[theId].fromAccount; // tokenPairs[i].toChainID = mapTokenPairInfo[theId].toChainID; // tokenPairs[i].toAccount = mapTokenPairInfo[theId].toAccount; // tokenPairs[i].id = theId; // } // } function getTokenPairs() external view returns (uint[] id, uint[] fromChainID, bytes[] fromAccount, uint[] toChainID, bytes[] toAccount, string[] ancestorSymbol, uint8[] ancestorDecimals, bytes[] ancestorAccount, string[] ancestorName, uint[] ancestorChainID) { uint cnt = totalTokenPairs; uint theId = 0; uint i = 0; id = new uint[](cnt); fromChainID = new uint[](cnt); fromAccount = new bytes[](cnt); toChainID = new uint[](cnt); toAccount = new bytes[](cnt); ancestorSymbol = new string[](cnt); ancestorDecimals = new uint8[](cnt); ancestorAccount = new bytes[](cnt); ancestorName = new string[](cnt); ancestorChainID = new uint[](cnt); i = 0; theId = 0; uint j = 0; for (; j < totalTokenPairs; j++) { theId = mapTokenPairIndex[j]; id[i] = theId; fromChainID[i] = mapTokenPairInfo[theId].fromChainID; fromAccount[i] = mapTokenPairInfo[theId].fromAccount; toChainID[i] = mapTokenPairInfo[theId].toChainID; toAccount[i] = mapTokenPairInfo[theId].toAccount; ancestorSymbol[i] = mapTokenPairInfo[theId].aInfo.symbol; ancestorDecimals[i] = mapTokenPairInfo[theId].aInfo.decimals; ancestorAccount[i] = mapTokenPairInfo[theId].aInfo.account; ancestorName[i] = mapTokenPairInfo[theId].aInfo.name; ancestorChainID[i] = mapTokenPairInfo[theId].aInfo.chainID; i ++; } } function getTokenPairsByChainID(uint chainID1, uint chainID2) external view returns (uint[] id, uint[] fromChainID, bytes[] fromAccount, uint[] toChainID, bytes[] toAccount, string[] ancestorSymbol, uint8[] ancestorDecimals, bytes[] ancestorAccount, string[] ancestorName, uint[] ancestorChainID) { uint cnt = 0; uint i = 0; uint theId = 0; uint[] memory id_valid = new uint[](totalTokenPairs); for (; i < totalTokenPairs; i++ ) { theId = mapTokenPairIndex[i]; if ((mapTokenPairInfo[theId].fromChainID == chainID1) && (mapTokenPairInfo[theId].toChainID == chainID2) || (mapTokenPairInfo[theId].toChainID == chainID1) && (mapTokenPairInfo[theId].fromChainID == chainID2)) { id_valid[cnt] = theId; cnt ++; } } id = new uint[](cnt); fromChainID = new uint[](cnt); fromAccount = new bytes[](cnt); toChainID = new uint[](cnt); toAccount = new bytes[](cnt); ancestorSymbol = new string[](cnt); ancestorDecimals = new uint8[](cnt); ancestorAccount = new bytes[](cnt); ancestorName = new string[](cnt); ancestorChainID = new uint[](cnt); for (i = 0; i < cnt; i++) { theId = id_valid[i]; id[i] = theId; fromChainID[i] = mapTokenPairInfo[theId].fromChainID; fromAccount[i] = mapTokenPairInfo[theId].fromAccount; toChainID[i] = mapTokenPairInfo[theId].toChainID; toAccount[i] = mapTokenPairInfo[theId].toAccount; ancestorSymbol[i] = mapTokenPairInfo[theId].aInfo.symbol; ancestorDecimals[i] = mapTokenPairInfo[theId].aInfo.decimals; ancestorAccount[i] = mapTokenPairInfo[theId].aInfo.account; ancestorName[i] = mapTokenPairInfo[theId].aInfo.name; ancestorChainID[i] = mapTokenPairInfo[theId].aInfo.chainID; } } }
contracts/crossApproach/CrossStorageV4.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; import "./CrossStorageV3.sol"; contract CrossStorageV4 is CrossStorageV3 { /************************************************************ ** ** VARIABLES ** ************************************************************/ uint internal maxBatchSize; }
contracts/interfaces/ISignatureVerifier.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; interface ISignatureVerifier { function verify( uint curveId, bytes32 signature, bytes32 groupKeyX, bytes32 groupKeyY, bytes32 randomPointX, bytes32 randomPointY, bytes32 message ) external returns (bool); }
contracts/crossApproach/CrossStorageV3.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; import "./CrossStorageV2.sol"; contract CrossStorageV3 is CrossStorageV2 { /************************************************************ ** ** VARIABLES ** ************************************************************/ /** STATE VARIABLES **/ // tokenPairID => fee mapping(uint256 => uint256) mapTokenPairContractFee; struct SetTokenPairFeesParam { uint256 tokenPairID; uint256 contractFee; } }
contracts/test/TestOrigTokenCreator.sol
pragma solidity ^0.4.24; import "../interfaces/IMappingToken.sol"; import "../tokenManager/MappingToken.sol"; import "../components/WRC20Protocol.sol"; import "../components/BasicStorage.sol"; import "./TestIOwned.sol"; contract TestOrigTokenCreator is BasicStorage { address _admin; modifier onlyAdmin { require(_admin != address(0), "admin is null"); _; } function setAdmin(address admin) external { _admin = admin; } function getAdmin() external view returns (address) { return _admin; } function createToken(string tokenName, string tokenSymbol, uint8 tokenDecimal) external { address tokenInst = new MappingToken(tokenName, tokenSymbol, tokenDecimal); addressData.setStorage(bytes(tokenName), bytes(tokenSymbol), tokenInst); uintData.setStorage(bytes(tokenName), bytes(tokenSymbol), tokenDecimal); // TestIOwned(tokenInst).changeOwner(msg.sender); } function changeOwner(string tokenName, string tokenSymbol) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); TestIOwned(tokenInst).changeOwner(msg.sender); } function acceptOwnership(string tokenName, string tokenSymbol) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); TestIOwned(tokenInst).acceptOwnership(); } function getTokenAddr(string tokenName, string tokenSymbol) external view returns (address) { return addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); } function mintToken(string tokenName, string tokenSymbol, address to, uint value) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); IMappingToken(tokenInst).mint(to, value); } function burnToken(string tokenName, string tokenSymbol, address from, uint value) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); IMappingToken(tokenInst).burn(from, value); } function tokenBalance(string tokenName, string tokenSymbol, address owner) external view returns (uint balance) { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); balance = WRC20Protocol(tokenInst).balanceOf(owner); } function getTokenDecimal(string tokenName, string tokenSymbol) external view returns (uint8) { return uint8(uintData.getStorage(bytes(tokenName), bytes(tokenSymbol))); } function destroyToken(string tokenName, string tokenSymbol) external { addressData.delStorage(bytes(tokenName), bytes(tokenSymbol)); uintData.delStorage(bytes(tokenName), bytes(tokenSymbol)); } }
contracts/crossApproach/lib/RapidityLibV4.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./RapidityTxLib.sol"; import "./CrossTypesV1.sol"; import "../../interfaces/ITokenManager.sol"; import "../../interfaces/IRC20Protocol.sol"; library RapidityLibV4 { using SafeMath for uint; using RapidityTxLib for RapidityTxLib.Data; enum TokenCrossType {ERC20, ERC721, ERC1155} /** * * STRUCTURES * */ /// @notice struct of Rapidity storeman mint lock parameters struct RapidityUserLockParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint currentChainID; /// current chain ID uint tokenPairContractFee; /// fee of token pair bytes destUserAccount; /// account of shadow chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity storeman mint lock parameters struct RapiditySmgMintParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint fee; /// exchange token fee address destTokenAccount; /// shadow token account address destUserAccount; /// account of shadow chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity user burn lock parameters struct RapidityUserBurnParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint currentChainID; /// current chain ID uint fee; /// exchange token fee uint tokenPairContractFee; /// fee of token pair address srcTokenAccount; /// shadow token account bytes destUserAccount; /// account of token destination chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity user burn lock parameters struct RapiditySmgReleaseParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint fee; /// exchange token fee address destTokenAccount; /// original token/coin account address destUserAccount; /// account of token original chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /** * * EVENTS * **/ /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity original token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserLockLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint contractFee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity shadow token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserBurnLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint contractFee, uint fee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param tokenAccount Rapidity shadow token account /// @param userAccount account of original chain, used to receive token event SmgMintLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, address tokenAccount, address userAccount); event SmgMint(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, string[] keys, bytes[] values); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param tokenAccount Rapidity original token account /// @param userAccount account of original chain, used to receive token event SmgReleaseLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, address tokenAccount, address userAccount); event SmgRelease(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, string[] keys, bytes[] values); /** * * MANIPULATIONS * */ /// @notice mintBridge, user lock token on token original chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for user mint lock token on token original chain function userLock(CrossTypesV1.Data storage storageData, RapidityUserLockParams memory params) public { ITokenManager tokenManager = storageData.tokenManager; uint fromChainID; uint toChainID; bytes memory fromTokenAccount; bytes memory toTokenAccount; (fromChainID,fromTokenAccount,toChainID,toTokenAccount) = tokenManager.getTokenPairInfo(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); uint contractFee = params.tokenPairContractFee; address tokenScAddr; if (params.currentChainID == fromChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[fromChainID][toChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(fromTokenAccount); } else if (params.currentChainID == toChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[toChainID][fromChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(toTokenAccount); } else { require(false, "Invalid token pair"); } if (contractFee > 0) { params.smgFeeProxy.transfer(contractFee); } uint left; if (tokenScAddr == address(0)) { left = (msg.value).sub(params.value).sub(contractFee); } else { left = (msg.value).sub(contractFee); uint8 tokenCrossType = tokenManager.mapTokenPairType(params.tokenPairID); require(tokenCrossType == uint8(TokenCrossType.ERC20), "Not support"); require(CrossTypesV1.transferFrom(tokenScAddr, msg.sender, address(this), params.value), "Lock token failed"); } if (left != 0) { (msg.sender).transfer(left); } emit UserLockLogger(params.smgID, params.tokenPairID, tokenScAddr, params.value, contractFee, params.destUserAccount); } /// @notice burnBridge, user lock token on token original chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for user burn lock token on token original chain function userBurn(CrossTypesV1.Data storage storageData, RapidityUserBurnParams memory params) public { ITokenManager tokenManager = storageData.tokenManager; uint fromChainID; uint toChainID; bytes memory fromTokenAccount; bytes memory toTokenAccount; (fromChainID,fromTokenAccount,toChainID,toTokenAccount) = tokenManager.getTokenPairInfo(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); uint256 contractFee = params.tokenPairContractFee; address tokenScAddr; if (params.currentChainID == toChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[toChainID][fromChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(toTokenAccount); } else if (params.currentChainID == fromChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[fromChainID][toChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(fromTokenAccount); } else { require(false, "Invalid token pair"); } require(params.srcTokenAccount == tokenScAddr, "Invalid token account"); // Reuse variable fromChainID as tokenCrossType; burn token by tokenCrossType fromChainID = tokenManager.mapTokenPairType(params.tokenPairID); require(fromChainID == uint8(TokenCrossType.ERC20), "Not support"); require(burnShadowToken(tokenManager, tokenScAddr, msg.sender, params.value), "Burn failed"); if (contractFee > 0) { params.smgFeeProxy.transfer(contractFee); } uint left = (msg.value).sub(contractFee); if (left != 0) { (msg.sender).transfer(left); } emit UserBurnLogger(params.smgID, params.tokenPairID, tokenScAddr, params.value, contractFee, params.fee, params.destUserAccount); } /// @notice mintBridge, storeman mint lock token on token shadow chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for storeman mint lock token on token shadow chain function smgMint(CrossTypesV1.Data storage storageData, RapiditySmgMintParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); ITokenManager tokenManager = storageData.tokenManager; uint8 tokenCrossType = tokenManager.mapTokenPairType(params.tokenPairID); require(tokenCrossType == uint8(TokenCrossType.ERC20), "Not support"); if (params.fee > 0) { require(mintShadowToken(tokenManager, params.destTokenAccount, params.smgFeeProxy, params.fee), "Mint fee failed"); } require(mintShadowToken(tokenManager, params.destTokenAccount, params.destUserAccount, params.value), "Mint failed"); string[] memory keys = new string[](4); bytes[] memory values = new bytes[](4); keys[0] = "value:uint256"; values[0] = abi.encodePacked(params.value); keys[1] = "tokenAccount:address"; values[1] = abi.encodePacked(params.destTokenAccount); keys[2] = "userAccount:address"; values[2] = abi.encodePacked(params.destUserAccount); keys[3] = "fee:uint256"; values[3] = abi.encodePacked(params.fee); emit SmgMint(params.uniqueID, params.smgID, params.tokenPairID, keys, values); emit SmgMintLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.destTokenAccount, params.destUserAccount); } /// @notice burnBridge, storeman burn lock token on token shadow chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for storeman burn lock token on token shadow chain function smgRelease(CrossTypesV1.Data storage storageData, RapiditySmgReleaseParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); if (params.destTokenAccount == address(0)) { (params.destUserAccount).transfer(params.value); if (params.fee > 0) { params.smgFeeProxy.transfer(params.fee); } } else { uint8 tokenCrossType = storageData.tokenManager.mapTokenPairType(params.tokenPairID); require(tokenCrossType == uint8(TokenCrossType.ERC20), "Not support"); if (params.fee > 0) { require(CrossTypesV1.transfer(params.destTokenAccount, params.smgFeeProxy, params.fee), "Transfer token fee failed"); } require(CrossTypesV1.transfer(params.destTokenAccount, params.destUserAccount, params.value), "Transfer token failed"); } string[] memory keys = new string[](4); bytes[] memory values = new bytes[](4); keys[0] = "value:uint256"; values[0] = abi.encodePacked(params.value); keys[1] = "tokenAccount:address"; values[1] = abi.encodePacked(params.destTokenAccount); keys[2] = "userAccount:address"; values[2] = abi.encodePacked(params.destUserAccount); keys[3] = "fee:uint256"; values[3] = abi.encodePacked(params.fee); emit SmgRelease(params.uniqueID, params.smgID, params.tokenPairID, keys, values); emit SmgReleaseLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.destTokenAccount, params.destUserAccount); } function burnShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).burnToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.sub(value); } function mintShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).mintToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.add(value); } }
contracts/crossApproach/lib/HTLCTxLib.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; library HTLCTxLib { using SafeMath for uint; /** * * ENUMS * */ /// @notice tx info status /// @notice uninitialized,locked,redeemed,revoked enum TxStatus {None, Locked, Redeemed, Revoked, AssetLocked, DebtLocked} /** * * STRUCTURES * */ /// @notice struct of HTLC user mint lock parameters struct HTLCUserParams { bytes32 xHash; /// hash of HTLC random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint lockFee; /// exchange token value uint lockedTime; /// HTLC lock time } /// @notice HTLC(Hashed TimeLock Contract) tx info struct BaseTx { bytes32 smgID; /// HTLC transaction storeman ID uint lockedTime; /// HTLC transaction locked time uint beginLockedTime; /// HTLC transaction begin locked time TxStatus status; /// HTLC transaction status } /// @notice user tx info struct UserTx { BaseTx baseTx; uint tokenPairID; uint value; uint fee; address userAccount; /// HTLC transaction sender address for the security check while user's revoke } /// @notice storeman tx info struct SmgTx { BaseTx baseTx; uint tokenPairID; uint value; address userAccount; /// HTLC transaction user address for the security check while user's redeem } /// @notice storeman debt tx info struct DebtTx { BaseTx baseTx; bytes32 srcSmgID; /// HTLC transaction sender(source storeman) ID } struct Data { /// @notice mapping of hash(x) to UserTx -- xHash->htlcUserTxData mapping(bytes32 => UserTx) mapHashXUserTxs; /// @notice mapping of hash(x) to SmgTx -- xHash->htlcSmgTxData mapping(bytes32 => SmgTx) mapHashXSmgTxs; /// @notice mapping of hash(x) to DebtTx -- xHash->htlcDebtTxData mapping(bytes32 => DebtTx) mapHashXDebtTxs; } /** * * MANIPULATIONS * */ /// @notice add user transaction info /// @param params parameters for user tx function addUserTx(Data storage self, HTLCUserParams memory params) public { UserTx memory userTx = self.mapHashXUserTxs[params.xHash]; // UserTx storage userTx = self.mapHashXUserTxs[params.xHash]; // require(params.value != 0, "Value is invalid"); require(userTx.baseTx.status == TxStatus.None, "User tx exists"); userTx.baseTx.smgID = params.smgID; userTx.baseTx.lockedTime = params.lockedTime; userTx.baseTx.beginLockedTime = now; userTx.baseTx.status = TxStatus.Locked; userTx.tokenPairID = params.tokenPairID; userTx.value = params.value; userTx.fee = params.lockFee; userTx.userAccount = msg.sender; self.mapHashXUserTxs[params.xHash] = userTx; } /// @notice refund coins from HTLC transaction, which is used for storeman redeem(outbound) /// @param x HTLC random number function redeemUserTx(Data storage self, bytes32 x) external returns(bytes32 xHash) { xHash = sha256(abi.encodePacked(x)); UserTx storage userTx = self.mapHashXUserTxs[xHash]; require(userTx.baseTx.status == TxStatus.Locked, "Status is not locked"); require(now < userTx.baseTx.beginLockedTime.add(userTx.baseTx.lockedTime), "Redeem timeout"); userTx.baseTx.status = TxStatus.Redeemed; return xHash; } /// @notice revoke user transaction /// @param xHash hash of HTLC random number function revokeUserTx(Data storage self, bytes32 xHash) external { UserTx storage userTx = self.mapHashXUserTxs[xHash]; require(userTx.baseTx.status == TxStatus.Locked, "Status is not locked"); require(now >= userTx.baseTx.beginLockedTime.add(userTx.baseTx.lockedTime), "Revoke is not permitted"); userTx.baseTx.status = TxStatus.Revoked; } /// @notice function for get user info /// @param xHash hash of HTLC random number /// @return smgID ID of storeman which user has selected /// @return tokenPairID token pair ID of cross chain /// @return value exchange value /// @return fee exchange fee /// @return userAccount HTLC transaction sender address for the security check while user's revoke function getUserTx(Data storage self, bytes32 xHash) external view returns (bytes32, uint, uint, uint, address) { UserTx storage userTx = self.mapHashXUserTxs[xHash]; return (userTx.baseTx.smgID, userTx.tokenPairID, userTx.value, userTx.fee, userTx.userAccount); } /// @notice add storeman transaction info /// @param xHash hash of HTLC random number /// @param smgID ID of the storeman which user has selected /// @param tokenPairID token pair ID of cross chain /// @param value HTLC transfer value of token /// @param userAccount user account address on the destination chain, which is used to redeem token function addSmgTx(Data storage self, bytes32 xHash, bytes32 smgID, uint tokenPairID, uint value, address userAccount, uint lockedTime) external { SmgTx memory smgTx = self.mapHashXSmgTxs[xHash]; // SmgTx storage smgTx = self.mapHashXSmgTxs[xHash]; require(value != 0, "Value is invalid"); require(smgTx.baseTx.status == TxStatus.None, "Smg tx exists"); smgTx.baseTx.smgID = smgID; smgTx.baseTx.status = TxStatus.Locked; smgTx.baseTx.lockedTime = lockedTime; smgTx.baseTx.beginLockedTime = now; smgTx.tokenPairID = tokenPairID; smgTx.value = value; smgTx.userAccount = userAccount; self.mapHashXSmgTxs[xHash] = smgTx; } /// @notice refund coins from HTLC transaction, which is used for users redeem(inbound) /// @param x HTLC random number function redeemSmgTx(Data storage self, bytes32 x) external returns(bytes32 xHash) { xHash = sha256(abi.encodePacked(x)); SmgTx storage smgTx = self.mapHashXSmgTxs[xHash]; require(smgTx.baseTx.status == TxStatus.Locked, "Status is not locked"); require(now < smgTx.baseTx.beginLockedTime.add(smgTx.baseTx.lockedTime), "Redeem timeout"); smgTx.baseTx.status = TxStatus.Redeemed; return xHash; } /// @notice revoke storeman transaction /// @param xHash hash of HTLC random number function revokeSmgTx(Data storage self, bytes32 xHash) external { SmgTx storage smgTx = self.mapHashXSmgTxs[xHash]; require(smgTx.baseTx.status == TxStatus.Locked, "Status is not locked"); require(now >= smgTx.baseTx.beginLockedTime.add(smgTx.baseTx.lockedTime), "Revoke is not permitted"); smgTx.baseTx.status = TxStatus.Revoked; } /// @notice function for get smg info /// @param xHash hash of HTLC random number /// @return smgID ID of storeman which user has selected /// @return tokenPairID token pair ID of cross chain /// @return value exchange value /// @return userAccount user account address for redeem function getSmgTx(Data storage self, bytes32 xHash) external view returns (bytes32, uint, uint, address) { SmgTx storage smgTx = self.mapHashXSmgTxs[xHash]; return (smgTx.baseTx.smgID, smgTx.tokenPairID, smgTx.value, smgTx.userAccount); } /// @notice add storeman transaction info /// @param xHash hash of HTLC random number /// @param srcSmgID ID of source storeman group /// @param destSmgID ID of the storeman which will take over of the debt of source storeman group /// @param lockedTime HTLC lock time /// @param status Status, should be 'Locked' for asset or 'DebtLocked' for debt function addDebtTx(Data storage self, bytes32 xHash, bytes32 srcSmgID, bytes32 destSmgID, uint lockedTime, TxStatus status) external { DebtTx memory debtTx = self.mapHashXDebtTxs[xHash]; // DebtTx storage debtTx = self.mapHashXDebtTxs[xHash]; require(debtTx.baseTx.status == TxStatus.None, "Debt tx exists"); debtTx.baseTx.smgID = destSmgID; debtTx.baseTx.status = status;//TxStatus.Locked; debtTx.baseTx.lockedTime = lockedTime; debtTx.baseTx.beginLockedTime = now; debtTx.srcSmgID = srcSmgID; self.mapHashXDebtTxs[xHash] = debtTx; } /// @notice refund coins from HTLC transaction /// @param x HTLC random number /// @param status Status, should be 'Locked' for asset or 'DebtLocked' for debt function redeemDebtTx(Data storage self, bytes32 x, TxStatus status) external returns(bytes32 xHash) { xHash = sha256(abi.encodePacked(x)); DebtTx storage debtTx = self.mapHashXDebtTxs[xHash]; // require(debtTx.baseTx.status == TxStatus.Locked, "Status is not locked"); require(debtTx.baseTx.status == status, "Status is not locked"); require(now < debtTx.baseTx.beginLockedTime.add(debtTx.baseTx.lockedTime), "Redeem timeout"); debtTx.baseTx.status = TxStatus.Redeemed; return xHash; } /// @notice revoke debt transaction, which is used for source storeman group /// @param xHash hash of HTLC random number /// @param status Status, should be 'Locked' for asset or 'DebtLocked' for debt function revokeDebtTx(Data storage self, bytes32 xHash, TxStatus status) external { DebtTx storage debtTx = self.mapHashXDebtTxs[xHash]; // require(debtTx.baseTx.status == TxStatus.Locked, "Status is not locked"); require(debtTx.baseTx.status == status, "Status is not locked"); require(now >= debtTx.baseTx.beginLockedTime.add(debtTx.baseTx.lockedTime), "Revoke is not permitted"); debtTx.baseTx.status = TxStatus.Revoked; } /// @notice function for get debt info /// @param xHash hash of HTLC random number /// @return srcSmgID ID of source storeman /// @return destSmgID ID of destination storeman function getDebtTx(Data storage self, bytes32 xHash) external view returns (bytes32, bytes32) { DebtTx storage debtTx = self.mapHashXDebtTxs[xHash]; return (debtTx.srcSmgID, debtTx.baseTx.smgID); } function getLeftTime(uint endTime) private view returns (uint) { if (now < endTime) { return endTime.sub(now); } return 0; } /// @notice function for get debt info /// @param xHash hash of HTLC random number /// @return leftTime the left lock time function getLeftLockedTime(Data storage self, bytes32 xHash) external view returns (uint) { UserTx storage userTx = self.mapHashXUserTxs[xHash]; if (userTx.baseTx.status != TxStatus.None) { return getLeftTime(userTx.baseTx.beginLockedTime.add(userTx.baseTx.lockedTime)); } SmgTx storage smgTx = self.mapHashXSmgTxs[xHash]; if (smgTx.baseTx.status != TxStatus.None) { return getLeftTime(smgTx.baseTx.beginLockedTime.add(smgTx.baseTx.lockedTime)); } DebtTx storage debtTx = self.mapHashXDebtTxs[xHash]; if (debtTx.baseTx.status != TxStatus.None) { return getLeftTime(debtTx.baseTx.beginLockedTime.add(debtTx.baseTx.lockedTime)); } require(false, 'invalid xHash'); } }
contracts/storemanGroupAdmin/StoremanLib.sol
pragma solidity ^0.4.24; import "./StoremanType.sol"; import "./StoremanUtil.sol"; import "../interfaces/IListGroup.sol"; library StoremanLib { using Deposit for Deposit.Records; using SafeMath for uint; uint constant MaxPartnerCount = 5; event stakeInEvent(bytes32 indexed groupId,address indexed wkAddr, address indexed from, uint value); event stakeAppendEvent(address indexed wkAddr, address indexed from, uint indexed value); event stakeOutEvent(address indexed wkAddr, address indexed from); event stakeClaimEvent(address indexed wkAddr, address indexed from,bytes32 indexed groupId, uint value); event stakeIncentiveClaimEvent(address indexed wkAddr,address indexed sender,uint indexed amount); event stakeIncentiveCrossFeeEvent(address indexed wkAddr,address indexed sender,uint indexed amount); event storemanTransferEvent(bytes32 indexed groupId, bytes32 indexed preGroupId, address[] wkAddrs); event StoremanGroupUnregisterEvent(bytes32 indexed groupId); event delegateInEvent(address indexed wkAddr, address indexed from, uint indexed value); event delegateOutEvent(address indexed wkAddr, address indexed from); event delegateClaimEvent(address indexed wkAddr, address indexed from, uint256 indexed amount); event delegateIncentiveClaimEvent(address indexed wkAddr,address indexed sender,uint indexed amount); event partInEvent(address indexed wkAddr, address indexed from, uint indexed value); event partOutEvent(address indexed wkAddr, address indexed from); event partClaimEvent(address indexed wkAddr, address indexed from, uint256 indexed amount); function storemanGroupUnregister(StoremanType.StoremanData storage data,bytes32 groupId) external { StoremanType.StoremanGroup storage group = data.groups[groupId]; require(now > group.workTime + group.totalTime, "not expired"); require(group.status == StoremanType.GroupStatus.ready,"Invalid status"); group.status = StoremanType.GroupStatus.unregistered; emit StoremanGroupUnregisterEvent(groupId); } function deleteStoremanNode(StoremanType.StoremanData storage data, address wkAddr) private { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; if(sk.deposit.getLastValue() == 0 && sk.delegatorCount == 0 && sk.partnerCount == 0) { delete data.candidates[0][wkAddr]; } } function stakeIn(StoremanType.StoremanData storage data, bytes32 groupId, bytes PK, bytes enodeID) external { StoremanType.StoremanGroup storage group = data.groups[groupId]; require(group.status == StoremanType.GroupStatus.curveSeted,"invalid group"); require(now <= group.registerTime+group.registerDuration,"Registration closed"); require(msg.value >= group.minStakeIn, "Too small value in stake"); require(StoremanUtil.onCurve(PK), "invalid PK"); require(StoremanUtil.onCurve(enodeID), "invalid enodeID"); address wkAddr = address(keccak256(PK)); StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; if(sk.sender != address(0x00)){ deleteStoremanNode(data, wkAddr); sk = data.candidates[0][wkAddr]; } require(sk.sender == address(0x00), "Candidate has existed"); sk.sender = msg.sender; sk.enodeID = enodeID; sk.PK = PK; sk.wkAddr = wkAddr; sk.groupId = groupId; sk.deposit = Deposit.Records(0); sk.deposit.addRecord(Deposit.Record(StoremanUtil.getDaybyTime(data.posLib, now), msg.value)); // only not whitelist address need add memberCount; if(!isWorkingNodeInGroup(group, wkAddr)) { group.skMap[group.memberCount] = sk.wkAddr; group.memberCount++; } // check if it is white if(group.whiteWk[wkAddr] != address(0x00)){ if(group.whiteWk[wkAddr] != msg.sender){ revert("invalid sender"); } sk.isWhite = true; // check if it is a backup whitelist, if yes, change it's groupId to 0. for(uint i=group.whiteCount; i<group.whiteCountAll; i++) { if(group.whiteMap[i] == wkAddr){ sk.groupId = bytes32(0x00); break; } } } else { realInsert(data,group, wkAddr, StoremanUtil.calSkWeight(data.conf.standaloneWeight, msg.value)); } emit stakeInEvent(groupId, wkAddr, msg.sender, msg.value); } function stakeAppend(StoremanType.StoremanData storage data, address wkAddr) external { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.wkAddr == wkAddr, "Candidate doesn't exist"); require(sk.sender == msg.sender, "Only the sender can stakeAppend"); uint amount = sk.deposit.getLastValue(); require(amount != 0, "Claimed"); uint day = StoremanUtil.getDaybyTime(data.posLib, now); Deposit.Record memory r = Deposit.Record(day, msg.value); Deposit.Record memory rw = Deposit.Record(day, StoremanUtil.calSkWeight(data.conf.standaloneWeight, msg.value)); sk.deposit.addRecord(r); StoremanType.StoremanGroup storage group = data.groups[sk.groupId]; StoremanType.StoremanGroup storage nextGroup = data.groups[sk.nextGroupId]; updateGroup(data, sk, group, r, rw); updateGroup(data, sk, nextGroup, r, rw); emit stakeAppendEvent(wkAddr, msg.sender,msg.value); } function checkCanStakeOut(StoremanType.StoremanData storage data, address wkAddr) public returns(bool){ StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.wkAddr == wkAddr, "Candidate doesn't exist"); StoremanType.StoremanGroup storage group = data.groups[sk.groupId]; StoremanType.StoremanGroup storage nextGroup = data.groups[sk.nextGroupId]; // if a group haven't selected, can't quit. // if the sk joined in the next group, and the next group haven't selected, cannot quit. //else change the flag quited==true if(group.status < StoremanType.GroupStatus.selected) { return false; } if(nextGroup.status != StoremanType.GroupStatus.none) { if(nextGroup.status < StoremanType.GroupStatus.selected){ return false; } } return true; } function stakeOut(StoremanType.StoremanData storage data, address wkAddr) external { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.sender == msg.sender, "Only the sender can stakeOut"); require(checkCanStakeOut(data, wkAddr),"selecting"); sk.quited = true; emit stakeOutEvent(wkAddr, msg.sender); } function isWorkingNodeInGroup(StoremanType.StoremanGroup storage group, address wkAddr) public view returns (bool) { uint count = group.selectedCount; for(uint8 i = 0; i < count; i++) { if(wkAddr == group.selectedNode[i]) { return true; } } return false; } function checkCanStakeClaimFromGroup(address posLib, StoremanType.Candidate storage sk, StoremanType.StoremanGroup storage group) private returns (bool) { // if group haven't selected, can't claim // if group failed, can claim. // if group selected and the sk haven't been selected, can claim. // if group selected and the sk was selected, then, must 1, group is dismissed. 2. incentived. if(group.status == StoremanType.GroupStatus.none) { return true; // group does not exist. } if(group.status == StoremanType.GroupStatus.failed) { return true; // group failed } if(group.status < StoremanType.GroupStatus.selected) { return false; } if(!isWorkingNodeInGroup(group, sk.wkAddr)){ return true; } else { if(group.status == StoremanType.GroupStatus.dismissed && sk.incentivedDay+1 >= StoremanUtil.getDaybyTime(posLib, group.workTime+group.totalTime) ) { return true; } } return false; } function checkCanStakeClaim(StoremanType.StoremanData storage data, address wkAddr) public returns(bool) { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; if(sk.wkAddr != wkAddr){ // sk doesn't exist. return false; } StoremanType.StoremanGroup storage group = data.groups[sk.groupId]; StoremanType.StoremanGroup storage nextGroup = data.groups[sk.nextGroupId]; if(checkCanStakeClaimFromGroup(data.posLib, sk, group) && checkCanStakeClaimFromGroup(data.posLib, sk, nextGroup)){ return true; } else { return false; } } function stakeClaim(StoremanType.StoremanData storage data, address wkAddr) external { require(checkCanStakeClaim(data,wkAddr),"Cannot claim"); StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; uint amount = sk.deposit.getLastValue(); require(amount != 0, "Claimed"); sk.deposit.clean(); // slash the node if(sk.slashedCount >= data.conf.maxSlashedCount) { amount = 0; } else { amount = amount.mul(data.conf.maxSlashedCount.sub(sk.slashedCount)).div(data.conf.maxSlashedCount); } emit stakeClaimEvent(wkAddr, sk.sender, sk.groupId, amount); // the cross chain fee emit stakeIncentiveCrossFeeEvent(wkAddr, sk.sender, sk.crossIncoming); amount = amount.add(sk.crossIncoming); sk.crossIncoming = 0; // the incentive emit stakeIncentiveClaimEvent(wkAddr,sk.sender,sk.incentive[0]); amount = amount.add(sk.incentive[0]); sk.incentive[0] = 0; sk.quited = true; if(amount != 0){ sk.sender.transfer(amount); } } function stakeIncentiveClaim(StoremanType.StoremanData storage data, address wkAddr) external { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.wkAddr == wkAddr, "Candidate doesn't exist"); uint amount = sk.incentive[0]; sk.incentive[0] = 0; if(amount != 0){ sk.sender.transfer(amount); } emit stakeIncentiveClaimEvent(wkAddr,sk.sender,amount); } function realInsert(StoremanType.StoremanData storage data, StoremanType.StoremanGroup storage group, address skAddr, uint weight) internal{ for (uint i = group.whiteCount; i < group.selectedCount; i++) { StoremanType.Candidate storage cmpNode = data.candidates[0][group.selectedNode[i]]; if (cmpNode.wkAddr == skAddr) { // keep self position, do not sort return; } uint cmpWeight = StoremanUtil.calSkWeight(data.conf.standaloneWeight, cmpNode.deposit.getLastValue().add(cmpNode.partnerDeposit)).add(cmpNode.delegateDeposit); if (weight > cmpWeight) { break; } } if (i < group.memberCountDesign) { address curAddr = group.selectedNode[i]; // must not be skAddr for (uint j = i; j < group.selectedCount; j++) { if (j + 1 < group.memberCountDesign) { address nextAddr = group.selectedNode[j + 1]; group.selectedNode[j + 1] = curAddr; if (nextAddr != skAddr) { curAddr = nextAddr; } else { break; } } } // insert or move to place i group.selectedNode[i] = skAddr; if ((group.selectedCount < group.memberCountDesign) && (j == group.selectedCount)) { group.selectedCount++; } } } function updateGroup(StoremanType.StoremanData storage data,StoremanType.Candidate storage sk, StoremanType.StoremanGroup storage group, Deposit.Record r, Deposit.Record rw) internal { //if haven't selected, need not update group. // if selected, need to update group. if(group.status == StoremanType.GroupStatus.none){ // not exist group. return; } //address wkAddr = sk.wkAddr; if(group.status == StoremanType.GroupStatus.curveSeted) { if(group.whiteWk[sk.wkAddr] == address(0x00)){ realInsert(data, group, sk.wkAddr, StoremanUtil.calSkWeight(data.conf.standaloneWeight, sk.deposit.getLastValue().add(sk.partnerDeposit)).add(sk.delegateDeposit)); } } else { if(isWorkingNodeInGroup(group, sk.wkAddr)){ group.deposit.addRecord(r); group.depositWeight.addRecord(rw); } } } function delegateIn(StoremanType.StoremanData storage data, address wkAddr) external { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.wkAddr == wkAddr, "Candidate doesn't exist"); StoremanType.StoremanGroup storage group = data.groups[sk.groupId]; StoremanType.StoremanGroup storage nextGroup = data.groups[sk.nextGroupId]; require(msg.value >= group.minDelegateIn, "Too small value"); //require(sk.delegateDeposit.add(msg.value) <= sk.deposit.getLastValue().mul(data.conf.DelegationMulti), "Too many delegation"); require(sk.delegateDeposit.add(msg.value) <= (sk.deposit.getLastValue().add(sk.partnerDeposit)).mul(data.conf.DelegationMulti), "Too many delegation"); StoremanType.Delegator storage dk = sk.delegators[msg.sender]; require(dk.quited == false, "Quited"); if(dk.deposit.getLastValue() == 0) { sk.delegatorMap[sk.delegatorCount] = msg.sender; dk.index = sk.delegatorCount; sk.delegatorCount = sk.delegatorCount.add(1); // dk.sender = msg.sender; // dk.staker = wkAddr; } sk.delegateDeposit = sk.delegateDeposit.add(msg.value); uint day = StoremanUtil.getDaybyTime(data.posLib, now); Deposit.Record memory r = Deposit.Record(day, msg.value); dk.deposit.addRecord(r); updateGroup(data, sk, group, r, r); updateGroup(data, sk, nextGroup, r, r); emit delegateInEvent(wkAddr, msg.sender,msg.value); } // must specify all the whitelist. function inheritNode(StoremanType.StoremanData storage data, bytes32 groupId, bytes32 preGroupId, address[] wkAddrs, address[] senders) public { StoremanType.StoremanGroup storage group = data.groups[groupId]; uint len = 0; if(preGroupId != bytes32(0x00)) { StoremanType.StoremanGroup storage oldGroup = data.groups[preGroupId]; len = oldGroup.memberCountDesign * 2; }else { len = wkAddrs.length; } address[] memory oldAddr = new address[](len); uint oldCount = 0; uint k = 0; group.whiteCount = wkAddrs.length.sub(data.conf.backupCount); group.whiteCountAll = wkAddrs.length; for(k = 0; k < wkAddrs.length; k++){ group.whiteMap[k] = wkAddrs[k]; group.whiteWk[wkAddrs[k]] = senders[k]; StoremanType.Candidate storage skw = data.candidates[0][wkAddrs[k]]; if(skw.wkAddr != address(0x00)){ // this node has exist if(preGroupId != bytes32(0x00)) { require(skw.groupId == bytes32(0x00) || skw.groupId == preGroupId, "Invalid whitelist"); } require(!skw.quited, "Invalid node"); oldAddr[oldCount] = wkAddrs[k]; oldCount++; } if(k < group.whiteCount) { group.selectedNode[k] = wkAddrs[k]; if(skw.groupId==bytes32(0x00)){ skw.groupId = groupId; } else { skw.nextGroupId = groupId; } } } group.selectedCount = group.whiteCount; group.memberCount = group.selectedCount; if (preGroupId != bytes32(0x00)) { oldCount = inheritStaker(data, groupId, preGroupId, oldAddr, oldCount); } address[] memory oldArray = new address[](oldCount); for (k = 0; k < oldCount; k++) { oldArray[k] = oldAddr[k]; } emit storemanTransferEvent(groupId, preGroupId, oldArray); } function inheritStaker(StoremanType.StoremanData storage data, bytes32 groupId, bytes32 preGroupId, address[] oldAddr, uint oldCount) public returns(uint) { StoremanType.StoremanGroup storage group = data.groups[groupId]; StoremanType.StoremanGroup storage oldGroup = data.groups[preGroupId]; uint[] memory stakes = new uint[](oldGroup.memberCountDesign * 2); uint k; for (k = oldGroup.whiteCount; k < oldGroup.memberCountDesign; k++) { address wkAddr = oldGroup.selectedNode[k]; StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; if (sk.groupId == preGroupId && !sk.quited && sk.slashedCount == 0 && !sk.isWhite) { if (oldGroup.status == StoremanType.GroupStatus.failed){ sk.groupId = groupId; } else { sk.nextGroupId = groupId; } group.memberCount++; oldAddr[oldCount] = sk.wkAddr; stakes[oldCount] = StoremanUtil.calSkWeight(data.conf.standaloneWeight, sk.deposit.getLastValue().add(sk.partnerDeposit)).add(sk.delegateDeposit); oldCount++; } } inheritSortedStaker(group, oldAddr, stakes, oldCount.sub(group.memberCount.sub(group.whiteCount)), oldCount); return oldCount; } function inheritSortedStaker(StoremanType.StoremanGroup storage group, address[] addresses, uint[] stakes, uint start, uint end) public { while ((group.selectedCount < group.memberCount) && (group.selectedCount < group.memberCountDesign)) { uint maxIndex = start; for (uint i = (start + 1); i < end; i++) { if (stakes[i] > stakes[maxIndex]) { maxIndex = i; } } group.selectedNode[group.selectedCount] = addresses[maxIndex]; group.selectedCount++; if (maxIndex == start) { start += 1; } else { stakes[maxIndex] = 0; } } } function delegateOut(StoremanType.StoremanData storage data, address wkAddr, address listGroupAddr) external { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.wkAddr == wkAddr, "Candidate doesn't exist"); require(checkCanStakeOut(data, wkAddr),"selecting"); StoremanType.Delegator storage dk = sk.delegators[msg.sender]; require(dk.quited == false,"Quited"); require(dk.deposit.getLastValue() != 0, "no deposit"); dk.quited = true; uint amount = dk.deposit.getLastValue(); sk.delegateDeposit = sk.delegateDeposit.sub(amount); IListGroup(listGroupAddr).setDelegateQuitGroupId(wkAddr, msg.sender, sk.groupId, sk.nextGroupId); emit delegateOutEvent(wkAddr, msg.sender); } function delegateClaim(StoremanType.StoremanData storage data, address wkAddr, address listGroupAddr) external { require(checkCanDelegatorClaim(data, wkAddr, msg.sender, listGroupAddr),"Cannot claim"); StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage dk = sk.delegators[msg.sender]; uint amount = dk.deposit.getLastValue(); require(amount != 0,"not exist"); dk.deposit.clean(); emit delegateClaimEvent(wkAddr, msg.sender, amount); if(!dk.quited) { sk.delegateDeposit = sk.delegateDeposit.sub(amount); } address lastDkAddr = sk.delegatorMap[sk.delegatorCount.sub(1)]; StoremanType.Delegator storage lastDk = sk.delegators[lastDkAddr]; sk.delegatorMap[dk.index] = lastDkAddr; lastDk.index = dk.index; emit delegateIncentiveClaimEvent(wkAddr,msg.sender,dk.incentive[0]); amount = amount.add(dk.incentive[0]); dk.incentive[0] = 0; sk.delegatorCount = sk.delegatorCount.sub(1); delete sk.delegatorMap[sk.delegatorCount]; delete sk.delegators[msg.sender]; IListGroup(listGroupAddr).setDelegateQuitGroupId(wkAddr, msg.sender, bytes32(0x00), bytes32(0x00)); msg.sender.transfer(amount); } function delegateIncentiveClaim(StoremanType.StoremanData storage data, address wkAddr) external { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.wkAddr == wkAddr, "Candidate doesn't exist"); StoremanType.Delegator storage dk = sk.delegators[msg.sender]; require(dk.deposit.getLastValue() != 0, "not exist"); uint amount = dk.incentive[0]; dk.incentive[0] = 0; if(amount!=0){ msg.sender.transfer(amount); } emit delegateIncentiveClaimEvent(wkAddr,msg.sender,amount); } function partIn(StoremanType.StoremanData storage data, address wkAddr) external { uint maxPartnerCount = 5; StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; require(sk.wkAddr == wkAddr, "Candidate doesn't exist"); StoremanType.StoremanGroup storage group = data.groups[sk.groupId]; StoremanType.StoremanGroup storage nextGroup = data.groups[sk.nextGroupId]; //require(msg.value >= group.minPartIn, "Too small value"); StoremanType.Delegator storage pn = sk.partners[msg.sender]; require(pn.quited == false, "Quited"); if(pn.deposit.getLastValue() == 0) { require(msg.value >= group.minPartIn, "Too small value"); require(sk.partnerCount<maxPartnerCount,"Too many partners"); sk.partMap[sk.partnerCount] = msg.sender; pn.index = sk.partnerCount; sk.partnerCount++; // pn.sender = msg.sender; // pn.staker = wkAddr; sk.partners[msg.sender] = pn; } sk.partnerDeposit = sk.partnerDeposit.add(msg.value); uint day = StoremanUtil.getDaybyTime(data.posLib, now); Deposit.Record memory r = Deposit.Record(day, msg.value); Deposit.Record memory rw = Deposit.Record(day, StoremanUtil.calSkWeight(data.conf.standaloneWeight, msg.value)); pn.deposit.addRecord(r); updateGroup(data, sk, group, r, rw); updateGroup(data, sk, nextGroup, r, rw); emit partInEvent(wkAddr, msg.sender, msg.value); } function partOut(StoremanType.StoremanData storage data, address wkAddr, address listGroupAddr) external { require(checkCanStakeOut(data, wkAddr),"selecting"); StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage pn = sk.partners[msg.sender]; require(pn.quited == false,"Quited"); require(pn.deposit.getLastValue() != 0, "Partner doesn't exist"); pn.quited = true; uint amount = pn.deposit.getLastValue(); sk.partnerDeposit = sk.partnerDeposit.sub(amount); IListGroup(listGroupAddr).setPartQuitGroupId(wkAddr, msg.sender, sk.groupId, sk.nextGroupId); emit partOutEvent(wkAddr, msg.sender); } function checkGroupTerminated(StoremanType.StoremanData storage data, bytes32 groupId) public returns(bool){ if(groupId == bytes32(0x00)) { return true; } StoremanType.StoremanGroup storage group = data.groups[groupId]; if(group.status == StoremanType.GroupStatus.none || group.status == StoremanType.GroupStatus.failed || group.status == StoremanType.GroupStatus.dismissed){ return true; } return false; } function checkCanPartnerClaim(StoremanType.StoremanData storage data, address wkAddr, address pnAddr, address listGroupAddr) public returns(bool) { if(checkCanStakeClaim(data,wkAddr)){ return true; } StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage pn = sk.partners[pnAddr]; bytes32 quitGroupId; bytes32 quitNextGroupId; (quitGroupId,quitNextGroupId) = IListGroup(listGroupAddr).getPartQuitGroupId(wkAddr, pnAddr); if(pn.quited && checkGroupTerminated(data, quitGroupId) && checkGroupTerminated(data, quitNextGroupId)){ return true; } return false; } function checkCanDelegatorClaim(StoremanType.StoremanData storage data, address wkAddr, address deAddr, address listGroupAddr) public returns(bool) { if(checkCanStakeClaim(data,wkAddr)){ return true; } StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage de = sk.delegators[deAddr]; bytes32 quitGroupId; bytes32 quitNextGroupId; (quitGroupId,quitNextGroupId) = IListGroup(listGroupAddr).getDelegateQuitGroupId(wkAddr, deAddr); if(de.quited && checkGroupTerminated(data, quitGroupId) && checkGroupTerminated(data, quitNextGroupId)){ return true; } return false; } function partClaim(StoremanType.StoremanData storage data, address wkAddr, address listGroupAddr) external { require(checkCanPartnerClaim(data,wkAddr, msg.sender,listGroupAddr),"Cannot claim"); StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage pn = sk.partners[msg.sender]; uint amount = pn.deposit.getLastValue(); require(amount != 0, "not exist"); pn.deposit.clean(); if(!pn.quited) { sk.partnerDeposit = sk.partnerDeposit.sub(amount); } address lastPnAddr = sk.partMap[sk.partnerCount.sub(1)]; StoremanType.Delegator storage lastPn = sk.partners[lastPnAddr]; sk.partMap[pn.index] = lastPnAddr; lastPn.index = pn.index; sk.partnerCount = sk.partnerCount.sub(1); delete sk.partMap[sk.partnerCount]; delete sk.partners[msg.sender]; IListGroup(listGroupAddr).setPartQuitGroupId(wkAddr, msg.sender, bytes32(0x00), bytes32(0x00)); // slash the node if(sk.slashedCount >= data.conf.maxSlashedCount) { amount = 0; } else { amount = amount.mul(data.conf.maxSlashedCount.sub(sk.slashedCount)).div(data.conf.maxSlashedCount); } emit partClaimEvent(wkAddr, msg.sender, amount); msg.sender.transfer(amount); } }
openzeppelin-eth/contracts/token/ERC721/IERC721.sol
pragma solidity ^0.4.24; import "../../zos-lib/Initializable.sol"; import "../../introspection/IERC165.sol"; /** * @title ERC721 Non-Fungible Token Standard basic interface * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721 is Initializable, IERC165 { event Transfer( address indexed from, address indexed to, uint256 indexed tokenId ); event Approval( address indexed owner, address indexed approved, uint256 indexed tokenId ); event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); function balanceOf(address owner) public view returns (uint256 balance); function ownerOf(uint256 tokenId) public view returns (address owner); function approve(address to, uint256 tokenId) public; function getApproved(uint256 tokenId) public view returns (address operator); function setApprovalForAll(address operator, bool _approved) public; function isApprovedForAll(address owner, address operator) public view returns (bool); function transferFrom(address from, address to, uint256 tokenId) public; function safeTransferFrom(address from, address to, uint256 tokenId) public; function safeTransferFrom( address from, address to, uint256 tokenId, bytes data ) public; }
contracts/metric/MetricDelegate.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; import "../components/Halt.sol"; import "./MetricStorage.sol"; import "./lib/MetricTypes.sol"; import "../interfaces/IStoremanGroup.sol"; import "../lib/CommonTool.sol"; import "./lib/MetricLib.sol"; import "../interfaces/IPosLib.sol"; contract MetricDelegate is MetricStorage, Halt{ using SafeMath for uint; using MetricLib for MetricTypes.MetricStorageData; /** * * MODIFIERS * */ modifier onlyLeader(bytes32 grpId) { address leader; leader = metricData.getLeader(grpId); require(msg.sender == leader, "Not leader"); _; } /** * * MANIPULATIONS * */ function getDependence() external view returns (address, address,address) { return (metricData.config, metricData.smg, metricData.posLib); } ///=======================================statistic============================================= /// @notice function for get incentive count of all store man during special epochs /// @param grpId group id /// @param startEpId start epoch id /// @param endEpId end epoch id function getPrdInctMetric(bytes32 grpId, uint startEpId, uint endEpId) external view returns (uint[]) { require(endEpId >= startEpId, "endEpId<startEpId"); uint[] memory ret; uint8 n = getSMCount(grpId); ret = new uint[](n); for (uint8 i = 0; i < n; i++) { for (uint j = startEpId; j <= endEpId; j++) { ret[i] = ret[i].add(metricData.mapInctCount[grpId][j][i]); } } return ret; } /// @notice function for get slash count of all store man during special epochs /// @param grpId group id /// @param startEpId start epoch id /// @param endEpId end epoch id function getPrdSlshMetric(bytes32 grpId, uint startEpId, uint endEpId) external view returns (uint[]) { require(endEpId >= startEpId, "endEpId<startEpId"); uint[] memory ret; uint8 n = getSMCount(grpId); ret = new uint[](n); for (uint8 i = 0; i < n; i++) { for (uint j = startEpId; j <= endEpId; j++) { ret[i] = ret[i].add(metricData.mapSlshCount[grpId][j][i]); } } return ret; } /// @notice function for get success count of sign data /// @param grpId group id /// @param epId epoch id /// @param smIndex index of store man function getSmSuccCntByEpId(bytes32 grpId, uint epId, uint8 smIndex) external view returns (uint) { return metricData.mapInctCount[grpId][epId][smIndex]; } /// @notice function for get slash count of one store man /// @param grpId group id /// @param epId epoch id /// @param smIndex index of store man function getSlshCntByEpId(bytes32 grpId, uint epId, uint8 smIndex) external view returns (uint) { return metricData.mapSlshCount[grpId][epId][smIndex]; } /// @notice function for get R stage slash proof of one store man /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function getRSlshProof(bytes32 grpId, bytes32 hashX, uint8 smIndex) external view returns (MetricTypes.RSlshData) { return metricData.mapRSlsh[grpId][hashX][smIndex]; } /// @notice function for get S stage slash proof of one store man /// @param grpId group id /// @param hashX hash of the signed data /// @param smIndex index of store man function getSSlshProof(bytes32 grpId, bytes32 hashX, uint8 smIndex) external view returns (MetricTypes.SSlshData) { return metricData.mapSSlsh[grpId][hashX][smIndex]; } ///=======================================write incentive and slash============================================= /// @notice function for write incentive data /// @param grpId group id /// @param hashX hash of the signed data /// @param inctData incentive store man's bitmap function wrInct(bytes32 grpId, bytes32 hashX, uint inctData) external notHalted onlyLeader(grpId) { require(metricData.mapInct[grpId][hashX].smIndexes == uint(0), 'Duplicate Incentive'); metricData.mapInct[grpId][hashX].smIndexes = inctData; uint8 smCount = getSMCount(grpId); uint epochId = getEpochId(); for (uint8 i = 0; i < smCount; i++) { if (checkHamming(inctData, i)) { metricData.mapInctCount[grpId][epochId][i] = metricData.mapInctCount[grpId][epochId][i].add(uint(1)); } } } /// @notice function for write R stage slash /// @param grpId group id /// @param hashX hash of the signed data /// @param rslshData data of slash function wrRSlsh(bytes32 grpId, bytes32 hashX, MetricTypes.RSlshData memory rslshData) public notHalted onlyLeader(grpId) { bool success; uint8 smIndex; (success, smIndex) = metricData.writeRSlsh(grpId, hashX, rslshData, getSMCount(grpId)); require(success, 'Fail to write R slsh'); metricData.recordSmSlash(grpId, smIndex); emit SMSlshLogger(grpId, hashX, smIndex, MetricTypes.SlshReason.R); } /// @notice function for write S stage slash /// @param grpId group id /// @param hashX hash of the signed data /// @param sslshData data of slash function wrSSlsh(bytes32 grpId, bytes32 hashX, MetricTypes.SSlshData memory sslshData) public notHalted onlyLeader(grpId) { bool success; uint8 smIndex; (success, smIndex) = metricData.writeSSlsh(grpId, hashX, sslshData, getSMCount(grpId)); require(success, 'Fail to write S Slsh'); metricData.recordSmSlash(grpId, smIndex); emit SMSlshLogger(grpId, hashX, smIndex, MetricTypes.SlshReason.S); } /// @notice function for set config and smg contract address /// @param configAddr config contract address /// @param smgAddr smg contract address function setDependence(address configAddr, address smgAddr, address posAddr) external onlyOwner { require(configAddr != address(0), "Invalid config address"); require(smgAddr != address(0), "Invalid smg address"); require(posAddr != address(0), "Invalid posLib address"); metricData.config = IConfig(configAddr); metricData.smg = IStoremanGroup(smgAddr); metricData.posLib = IPosLib(posAddr); } function getSMCount(bytes32 grpId) private view returns (uint8) { return uint8(metricData.getSMCount(grpId)); } function getEpochId() private view returns (uint) { return IPosLib(metricData.posLib).getEpochId(now); } function checkHamming(uint indexes, uint8 smIndex) private pure returns (bool) { return indexes & (uint(1) << smIndex) != uint(0); } function() public payable { revert("Not support"); } }
contracts/storemanGroupAdmin/StoremanGroupStorage.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.26; import "../components/BasicStorage.sol"; import "../interfaces/IMetric.sol"; import "./Deposit.sol"; import "./StoremanType.sol"; import "../interfaces/IQuota.sol"; contract StoremanGroupStorage is BasicStorage { address public metric; IQuota public quotaInst; address public createGpkAddr; StoremanType.StoremanData data; constructor() public { uint backupCountDefault = 3; uint maxSlashedCount = 2; uint standaloneWeightDefault = 15000; uint chainTypeCoDefault = 10000; uint DelegationMultiDefault = 5; data.conf.standaloneWeight = standaloneWeightDefault; data.conf.backupCount = backupCountDefault; data.conf.chainTypeCoDefault = chainTypeCoDefault; data.conf.maxSlashedCount = maxSlashedCount; data.conf.DelegationMulti = DelegationMultiDefault; } }
openzeppelin-eth/contracts/introspection/ERC165.sol
pragma solidity ^0.4.24; import "../zos-lib/Initializable.sol"; import "./IERC165.sol"; /** * @title ERC165 * @author Matt Condon (@shrugs) * @dev Implements ERC165 using a lookup table. */ contract ERC165 is Initializable, IERC165 { bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; /** * 0x01ffc9a7 === * bytes4(keccak256('supportsInterface(bytes4)')) */ /** * @dev a mapping of interface id to whether or not it's supported */ mapping(bytes4 => bool) internal _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup * implement ERC165 itself */ function initialize() public initializer { _registerInterface(_InterfaceId_ERC165); } /** * @dev implement supportsInterface(bytes4) using a lookup table */ function supportsInterface(bytes4 interfaceId) public view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev private method for registering an interface */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff); _supportedInterfaces[interfaceId] = true; } uint256[50] private ______gap; }
contracts/interfaces/ICurve.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; interface ICurve { function add(uint256 x1, uint256 y1, uint256 x2, uint256 y2) external view returns(uint256 retx, uint256 rety, bool success); function mulG(uint256 scalar) external view returns(uint256 x, uint256 y, bool success); function calPolyCommit(bytes polyCommit, bytes pk) external view returns(uint256 sx, uint256 sy, bool success); function mulPk(uint256 scalar, uint256 xPk, uint256 yPk) external view returns (uint256 x, uint256 y, bool success); function equalPt (uint256 xLeft, uint256 yLeft,uint256 xRight, uint256 yRight) external view returns(bool); function checkSig (bytes32 hash, bytes32 r, bytes32 s, bytes pk) external view returns(bool); }
contracts/components/Admin.sol
pragma solidity 0.4.26; import "./Owned.sol"; contract Admin is Owned { mapping(address => bool) public mapAdmin; event AddAdmin(address admin); event RemoveAdmin(address admin); modifier onlyAdmin() { require(mapAdmin[msg.sender], "not admin"); _; } function addAdmin( address admin ) external onlyOwner { mapAdmin[admin] = true; emit AddAdmin(admin); } function removeAdmin( address admin ) external onlyOwner { delete mapAdmin[admin]; emit RemoveAdmin(admin); } }
openzeppelin-eth/contracts/zos-lib/Initializable.sol
pragma solidity ^0.4.24; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool wasInitializing = initializing; initializing = true; initialized = true; _; initializing = wasInitializing; } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. uint256 cs; assembly { cs := extcodesize(address) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
contracts/crossApproach/CrossStorageV2.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; import "../components/Proxy.sol"; import "../components/Halt.sol"; import "../components/ReentrancyGuard.sol"; import "./CrossStorageV1.sol"; contract CrossStorageV2 is CrossStorageV1, ReentrancyGuard, Halt, Proxy { /************************************************************ ** ** VARIABLES ** ************************************************************/ /** STATE VARIABLES **/ uint256 public currentChainID; address public admin; /** STRUCTURES **/ struct SetFeesParam { uint256 srcChainID; uint256 destChainID; uint256 contractFee; uint256 agentFee; } struct GetFeesParam { uint256 srcChainID; uint256 destChainID; } struct GetFeesReturn { uint256 contractFee; uint256 agentFee; } }
openzeppelin-eth/contracts/ownership/Ownable.sol
pragma solidity ^0.4.24; import "../zos-lib/Initializable.sol"; /** * @title Ownable * @dev The Ownable contract has an owner address, and provides basic authorization control * functions, this simplifies the implementation of "user permissions". */ contract Ownable is Initializable { address private _owner; event OwnershipRenounced(address indexed previousOwner); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function initialize(address sender) public initializer { _owner = sender; } /** * @return the address of the owner. */ function owner() public view returns(address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns(bool) { return msg.sender == _owner; } /** * @dev Allows the current owner to relinquish control of the contract. * @notice Renouncing to ownership will leave the contract without an owner. * It will not be possible to call the functions with the `onlyOwner` * modifier anymore. */ function renounceOwnership() public onlyOwner { emit OwnershipRenounced(_owner); _owner = address(0); } /** * @dev Allows the current owner to transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) public onlyOwner { _transferOwnership(newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function _transferOwnership(address newOwner) internal { require(newOwner != address(0)); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } uint256[50] private ______gap; }
contracts/metric/MetricStorage.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../components/BasicStorage.sol"; import "./lib/MetricTypes.sol"; import "../interfaces/IConfig.sol"; import "../interfaces/IStoremanGroup.sol"; contract MetricStorage is BasicStorage { /** * * EVENTS * **/ event SMSlshLogger(bytes32 indexed groupId, bytes32 indexed hashX, uint8 indexed smIndex, MetricTypes.SlshReason slshReason); /************************************************************ ** ** VARIABLES ** ************************************************************/ MetricTypes.MetricStorageData public metricData; }
contracts/test/TestDeposit.sol
pragma solidity ^0.4.26; import "../storemanGroupAdmin/Deposit.sol"; contract TestDeposit { using Deposit for Deposit.Records; Deposit.Records g; constructor()public{ g.total = 0; return; } function add(uint id, uint v) public { Deposit.Record memory r = Deposit.Record(id, v); g.addRecord(r); } function clean()public { g.clean(); } function getTotal() public view returns (uint){ return g.total; } function getLastValue() public view returns(uint){ return g.getLastValue(); } function get(uint id) public view returns(uint value){ uint a = g.getValueById(id); return a; } }
contracts/tokenManager/TokenManagerStorage.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; import "../components/BasicStorage.sol"; contract TokenManagerStorage is BasicStorage { /************************************************************ ** ** STRUCTURE DEFINATIONS ** ************************************************************/ struct AncestorInfo { bytes account; string name; string symbol; uint8 decimals; uint chainID; } struct TokenPairInfo { AncestorInfo aInfo; /// TODO: uint fromChainID; /// index in coinType.txt; e.g. eth=60, etc=61, wan=5718350 bytes fromAccount; /// from address uint toChainID; /// bytes toAccount; /// to token address } struct TokenPairInfoFull { uint id; AncestorInfo aInfo; uint fromChainID; bytes fromAccount; uint toChainID; bytes toAccount; } /************************************************************ ** ** VARIABLES ** ************************************************************/ /// total amount of TokenPair instance uint public totalTokenPairs = 0; /// a map from a sequence ID to token pair mapping(uint => TokenPairInfo) public mapTokenPairInfo; // index -> tokenPairId mapping(uint => uint) public mapTokenPairIndex; }
contracts/oracle/OracleStorage.sol
pragma solidity 0.4.26; import "../components/BasicStorage.sol"; contract OracleStorage is BasicStorage { /************************************************************ ** ** STRUCTURE DEFINATIONS ** ************************************************************/ struct StoremanGroupConfig { uint deposit; uint[2] chain; uint[2] curve; bytes gpk1; bytes gpk2; uint startTime; uint endTime; uint8 status; bool isDebtClean; } /************************************************************ ** ** VARIABLES ** ************************************************************/ /// @notice symbol -> price, mapping(bytes32 => uint) public mapPrices; /// @notice smgId -> StoremanGroupConfig mapping(bytes32 => StoremanGroupConfig) public mapStoremanGroupConfig; /// @notice owner and admin have the authority of admin address public admin; }
contracts/storemanGroupAdmin/Deposit.sol
pragma solidity ^0.4.26; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; library Deposit { using SafeMath for uint; struct Record { uint id; uint value; // the value is current total value, include the old deposit } struct Records { uint total; mapping(uint=>Record) records; } function getLastValue(Records storage self) internal view returns (uint) { if(self.total == 0) { return 0; } else { return self.records[self.total-1].value; } } function getValueById(Records storage self, uint id) internal view returns (uint) { for (uint i = self.total; i > 0; i--) { if (id >= self.records[i-1].id){ return self.records[i-1].value; } } return 0; } function clean(Records storage self) internal { self.total = 0; } function addRecord(Records storage self, Record r) internal { if(self.total == 0) { self.records[0] = r; self.total = 1; } else { Record storage e = self.records[self.total-1]; if(e.id == r.id) { e.value = e.value.add(r.value); }else{ Record memory n = Record(r.id, r.value); n.value = n.value.add(self.records[self.total-1].value); self.records[self.total] = n; self.total++; } } } }
contracts/crossApproach/lib/HTLCDebtLibV2.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./CrossTypesV1.sol"; library HTLCDebtLibV2 { /** * * STRUCTURES * */ /// @notice struct of debt and asset parameters struct DebtAssetParams { bytes32 uniqueID; /// hash of HTLC random number bytes32 srcSmgID; /// ID of source storeman group bytes32 destSmgID; /// ID of destination storeman group } /** * * EVENTS * **/ /// @notice event of storeman asset transfer /// @param uniqueID random number /// @param srcSmgID ID of source storeman group /// @param destSmgID ID of destination storeman group event TransferAssetLogger(bytes32 indexed uniqueID, bytes32 indexed srcSmgID, bytes32 indexed destSmgID); /// @notice event of storeman debt receive /// @param uniqueID random number /// @param srcSmgID ID of source storeman group /// @param destSmgID ID of destination storeman group event ReceiveDebtLogger(bytes32 indexed uniqueID, bytes32 indexed srcSmgID, bytes32 indexed destSmgID); /** * * MANIPULATIONS * */ /// @notice transfer asset /// @param storageData Cross storage data /// @param params parameters of storeman debt lock function transferAsset(CrossTypesV1.Data storage storageData, DebtAssetParams memory params) public { if (address(storageData.quota) != address(0)) { storageData.quota.transferAsset(params.srcSmgID, params.destSmgID); } emit TransferAssetLogger(params.uniqueID, params.srcSmgID, params.destSmgID); } /// @notice receive debt /// @param storageData Cross storage data /// @param params parameters of storeman debt lock function receiveDebt(CrossTypesV1.Data storage storageData, DebtAssetParams memory params) public { if (address(storageData.quota) != address(0)) { storageData.quota.receiveDebt(params.srcSmgID, params.destSmgID); } emit ReceiveDebtLogger(params.uniqueID, params.srcSmgID, params.destSmgID); } }
contracts/storemanGroupAdmin/StoremanUtil.sol
pragma solidity ^0.4.24; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; import "./StoremanType.sol"; import "../interfaces/IPosLib.sol"; import "../lib/CommonTool.sol"; library StoremanUtil { using SafeMath for uint; function calSkWeight(uint standaloneWeight,uint deposit) public pure returns(uint) { return deposit*standaloneWeight/10000; } function getDaybyTime(address posLib, uint time) public view returns(uint) { return IPosLib(posLib).getEpochId(time); } function getSelectedSmNumber(StoremanType.StoremanData storage data, bytes32 groupId) public view returns(uint) { StoremanType.StoremanGroup storage group = data.groups[groupId]; return group.selectedCount; } function getSelectedStoreman(StoremanType.StoremanData storage data, bytes32 groupId) public view returns(address[]) { StoremanType.StoremanGroup storage group = data.groups[groupId]; address[] memory storemans = new address[](group.selectedCount); for(uint8 i=0; i<group.selectedCount; i++){ storemans[i] = group.selectedNode[i]; } return storemans; } function onCurve(bytes pubkey) public view returns (bool) { if(pubkey.length != 64) return false; uint[2] memory P; P[0] = CommonTool.bytes2uint(pubkey, 0, 32); P[1] = CommonTool.bytes2uint(pubkey, 32, 32); uint p = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; if (0 == P[0] || P[0] == p || 0 == P[1] || P[1] == p) return false; uint LHS = mulmod(P[1], P[1], p); uint RHS = addmod(mulmod(mulmod(P[0], P[0], p), P[0], p), 7, p); return LHS == RHS; } }
contracts/oracle/OracleProxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; import "../components/Owned.sol"; import "./OracleStorage.sol"; import "../components/Proxy.sol"; contract OracleProxy is OracleStorage, Owned, Proxy { /** * * MANIPULATIONS * */ /// @notice function for setting or upgrading OracleDelegate address by owner /// @param impl OracleDelegate contract address function upgradeTo(address impl) public onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require(impl != _implementation, "Cannot upgrade to the same implementation"); _implementation = impl; emit Upgraded(impl); } }
contracts/crossApproach/CrossStorageV1.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; import "../components/BasicStorage.sol"; import "./lib/CrossTypesV1.sol"; import "./lib/HTLCTxLib.sol"; import "./lib/RapidityTxLib.sol"; contract CrossStorageV1 is BasicStorage { using HTLCTxLib for HTLCTxLib.Data; using RapidityTxLib for RapidityTxLib.Data; /************************************************************ ** ** VARIABLES ** ************************************************************/ CrossTypesV1.Data internal storageData; /// @notice locked time(in seconds) uint public lockedTime = uint(3600*36); /// @notice Since storeman group admin receiver address may be changed, system should make sure the new address /// @notice can be used, and the old address can not be used. The solution is add timestamp. /// @notice unit: second uint public smgFeeReceiverTimeout = uint(10*60); enum GroupStatus { none, initial, curveSeted, failed, selected, ready, unregistered, dismissed } }
contracts/crossApproach/lib/RapidityLib.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./RapidityTxLib.sol"; import "./CrossTypes.sol"; import "../../interfaces/ITokenManager.sol"; import "../../interfaces/IRC20Protocol.sol"; import "../../interfaces/ISmgFeeProxy.sol"; library RapidityLib { using SafeMath for uint; using RapidityTxLib for RapidityTxLib.Data; /** * * STRUCTURES * */ /// @notice struct of Rapidity storeman mint lock parameters struct RapidityUserLockParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value bytes userShadowAccount; /// account of shadow chain, used to receive token } /// @notice struct of Rapidity storeman mint lock parameters struct RapiditySmgMintParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value address shadowTokenAccount; /// shadow token account address userShadowAccount; /// account of shadow chain, used to receive token } /// @notice struct of Rapidity user burn lock parameters struct RapidityUserBurnParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint fee; /// exchange token fee address shadowTokenAccount; /// shadow token account bytes userOrigAccount; /// account of token original chain, used to receive token } /// @notice struct of Rapidity user burn lock parameters struct RapiditySmgReleaseParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value address origTokenAccount; /// original token/coin account address userOrigAccount; /// account of token original chain, used to receive token } /** * * EVENTS * **/ /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity original token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserLockLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint serviceFee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity shadow token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserBurnLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint serviceFee, uint fee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param tokenAccount Rapidity shadow token account /// @param userAccount account of original chain, used to receive token event SmgMintLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, address tokenAccount, address userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param tokenAccount Rapidity original token account /// @param userAccount account of original chain, used to receive token event SmgReleaseLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, address tokenAccount, address userAccount); /** * * MANIPULATIONS * */ /// @notice mintBridge, user lock token on token original chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for user mint lock token on token original chain function userLock(CrossTypes.Data storage storageData, RapidityUserLockParams memory params) public { uint fromChainID; uint toChainID; bytes memory fromTokenAccount; (fromChainID,fromTokenAccount,toChainID) = storageData.tokenManager.getTokenPairInfoSlim(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); uint serviceFee = storageData.mapLockFee[fromChainID][toChainID]; if (address(storageData.quota) != address(0)) { storageData.quota.userLock(params.tokenPairID, params.smgID, params.value); } if (serviceFee > 0) { if (storageData.smgFeeProxy == address(0)) { storageData.mapStoremanFee[params.smgID] = storageData.mapStoremanFee[params.smgID].add(serviceFee); } else { ISmgFeeProxy(storageData.smgFeeProxy).smgTransfer.value(serviceFee)(params.smgID); } } address tokenScAddr = CrossTypes.bytesToAddress(fromTokenAccount); uint left; if (tokenScAddr == address(0)) { left = (msg.value).sub(params.value).sub(serviceFee); } else { left = (msg.value).sub(serviceFee); require(CrossTypes.transferFrom(tokenScAddr, msg.sender, this, params.value), "Lock token failed"); } if (left != 0) { (msg.sender).transfer(left); } emit UserLockLogger(params.smgID, params.tokenPairID, tokenScAddr, params.value, serviceFee, params.userShadowAccount); } /// @notice burnBridge, user lock token on token original chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for user burn lock token on token original chain function userBurn(CrossTypes.Data storage storageData, RapidityUserBurnParams memory params) public { ITokenManager tokenManager = storageData.tokenManager; uint fromChainID; uint toChainID; bytes memory fromTokenAccount; bytes memory toTokenAccount; (fromChainID,fromTokenAccount,toChainID,toTokenAccount) = tokenManager.getTokenPairInfo(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); address tokenScAddr = CrossTypes.bytesToAddress(toTokenAccount); uint serviceFee; if (tokenScAddr == params.shadowTokenAccount) { serviceFee = storageData.mapLockFee[fromChainID][toChainID]; } else { tokenScAddr = CrossTypes.bytesToAddress(fromTokenAccount); if (tokenScAddr == params.shadowTokenAccount) { serviceFee = storageData.mapLockFee[toChainID][fromChainID]; } else { require(false, "Invalid Token account"); } } if (address(storageData.quota) != address(0)) { storageData.quota.userBurn(params.tokenPairID, params.smgID, params.value); } require(burnShadowToken(tokenManager, tokenScAddr, msg.sender, params.value), "burn failed"); if (serviceFee > 0) { if (storageData.smgFeeProxy == address(0)) { storageData.mapStoremanFee[params.smgID] = storageData.mapStoremanFee[params.smgID].add(serviceFee); } else { ISmgFeeProxy(storageData.smgFeeProxy).smgTransfer.value(serviceFee)(params.smgID); } } uint left = (msg.value).sub(serviceFee); if (left != 0) { (msg.sender).transfer(left); } emit UserBurnLogger(params.smgID, params.tokenPairID, params.shadowTokenAccount, params.value, serviceFee, params.fee, params.userOrigAccount); } /// @notice mintBridge, storeman mint lock token on token shadow chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for storeman mint lock token on token shadow chain function smgMint(CrossTypes.Data storage storageData, RapiditySmgMintParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); if (address(storageData.quota) != address(0)) { storageData.quota.smgMint(params.tokenPairID, params.smgID, params.value); } require(mintShadowToken(storageData.tokenManager, params.shadowTokenAccount, params.userShadowAccount, params.value), "mint failed"); emit SmgMintLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.shadowTokenAccount, params.userShadowAccount); } /// @notice burnBridge, storeman burn lock token on token shadow chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for storeman burn lock token on token shadow chain function smgRelease(CrossTypes.Data storage storageData, RapiditySmgReleaseParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); if (address(storageData.quota) != address(0)) { storageData.quota.smgRelease(params.tokenPairID, params.smgID, params.value); } if (params.origTokenAccount == address(0)) { (params.userOrigAccount).transfer(params.value); } else { require(CrossTypes.transfer(params.origTokenAccount, params.userOrigAccount, params.value), "Transfer token failed"); } emit SmgReleaseLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.origTokenAccount, params.userOrigAccount); } function burnShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).burnToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.sub(value); } function mintShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).mintToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.add(value); } }
contracts/interfaces/IStoremanGroup.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; interface IStoremanGroup { function getSelectedSmNumber(bytes32 groupId) external view returns(uint number); function getStoremanGroupConfig(bytes32 id) external view returns(bytes32 groupId, uint8 status, uint deposit, uint chain1, uint chain2, uint curve1, uint curve2, bytes gpk1, bytes gpk2, uint startTime, uint endTime); function getDeposit(bytes32 id) external view returns(uint); function getStoremanGroupStatus(bytes32 id) external view returns(uint8 status, uint startTime, uint endTime); function setGpk(bytes32 groupId, bytes gpk1, bytes gpk2) external; function setInvalidSm(bytes32 groupId, uint[] indexs, uint8[] slashTypes) external returns(bool isContinue); function getThresholdByGrpId(bytes32 groupId) external view returns (uint); function getSelectedSmInfo(bytes32 groupId, uint index) external view returns(address wkAddr, bytes PK, bytes enodeId); function recordSmSlash(address wk) external; }
contracts/gpk/lib/GpkLib.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.24; import "../../lib/CommonTool.sol"; import "../../interfaces/IStoremanGroup.sol"; import "../../interfaces/ICurve.sol"; import "../../interfaces/IConfig.sol"; import "./GpkTypes.sol"; import "../../storemanGroupAdmin/StoremanType.sol"; library GpkLib { /// submit period uint32 constant DEFAULT_PERIOD = 2 * 60 * 60; // 2 hours uint32 constant PLOYCOMMIT_PERIOD = 48 * 60 * 60; // 48 hours uint32 constant NEGOTIATE_PERIOD = 6 * 60 * 60; // 6 hours /** * * EVENTS * */ /// @notice event for gpk created /// @param groupId storeman group id /// @param round group negotiate round /// @param gpk1 group public key for chain1 /// @param gpk2 group public key for chain2 event GpkCreatedLogger(bytes32 indexed groupId, uint16 indexed round, bytes gpk1, bytes gpk2); /// @notice event for contract slash storeman /// @param groupId storeman group id /// @param slashType the reason to slash /// @param slashed slashed storeman /// @param partner negotiate parter /// @param round group negotiate round /// @param curveIndex signature curve index event SlashLogger(bytes32 indexed groupId, uint8 indexed slashType, address indexed slashed, address partner, uint16 round, uint8 curveIndex); /// @notice event for group reset protocol /// @param groupId storeman group id /// @param round group negotiate round event ResetLogger(bytes32 indexed groupId, uint16 indexed round); /// @notice event for group close protocol /// @param groupId storeman group id /// @param round group negotiate max round event CloseLogger(bytes32 indexed groupId, uint16 indexed round); /** * * MANIPULATIONS * */ /// @notice function for init period /// @param groupId storeman group id /// @param group storeman group /// @param cfg group config /// @param smg storeman group contract address function initGroup(bytes32 groupId, GpkTypes.Group storage group, address cfg, address smg) public { // init period if (group.defaultPeriod == 0) { group.defaultPeriod = DEFAULT_PERIOD; group.ployCommitPeriod = PLOYCOMMIT_PERIOD; group.negotiatePeriod = NEGOTIATE_PERIOD; } // init signature curve uint8 status; uint256 curve1; uint256 curve2; (,status,,,,curve1,curve2,,,,) = IStoremanGroup(smg).getStoremanGroupConfig(groupId); require(status == uint8(StoremanType.GroupStatus.selected), "Invalid stage"); group.roundMap[group.round][0].curve = IConfig(cfg).getCurve(uint8(curve1)); group.roundMap[group.round][1].curve = IConfig(cfg).getCurve(uint8(curve2)); group.groupId = groupId; // retrieve selected sm list group.smNumber = uint16(IStoremanGroup(smg).getSelectedSmNumber(groupId)); address txAddress; bytes memory pk; for (uint i = 0; i < group.smNumber; i++) { (txAddress, pk,) = IStoremanGroup(smg).getSelectedSmInfo(groupId, i); group.addrMap[i] = txAddress; group.indexMap[txAddress] = i; group.pkMap[txAddress] = pk; } } /// @notice function for try to complete /// @param group storeman group function tryComplete(GpkTypes.Group storage group, address smg) public { GpkTypes.Round storage round1 = group.roundMap[group.round][0]; GpkTypes.Round storage round2 = group.roundMap[group.round][1]; if (round1.status == round2.status) { IStoremanGroup(smg).setGpk(group.groupId, round1.gpk, round2.gpk); emit GpkCreatedLogger(group.groupId, group.round, round1.gpk, round2.gpk); } } /// @notice function for update gpk /// @param round round /// @param polyCommit poly commit function updateGpk(GpkTypes.Round storage round, bytes polyCommit) public { bytes memory gpk = round.gpk; uint x = CommonTool.bytes2uint(polyCommit, 0, 32); uint y = CommonTool.bytes2uint(polyCommit, 32, 32); if (gpk.length != 0) { uint gpkX = CommonTool.bytes2uint(gpk, 0, 32); uint gpkY = CommonTool.bytes2uint(gpk, 32, 32); bool success; (x, y, success) = ICurve(round.curve).add(x, y, gpkX, gpkY); require(success == true, "Gpk failed"); } else { gpk = new bytes(64); } assembly { mstore(add(gpk, 32), x) } assembly { mstore(add(gpk, 64), y) } round.gpk = gpk; } /// @notice function for update gpkShare /// @param group storeman group /// @param round round /// @param polyCommit poly commit function updateGpkShare(GpkTypes.Group storage group, GpkTypes.Round storage round, bytes polyCommit) public { uint x; uint y; bool success; for (uint i = 0; i < group.smNumber; i++) { address txAddress = group.addrMap[i]; bytes memory pk = group.pkMap[txAddress]; (x, y, success) = ICurve(round.curve).calPolyCommit(polyCommit, pk); require(success == true, "PolyCommit failed"); bytes memory gpkShare = round.srcMap[txAddress].gpkShare; if (gpkShare.length != 0) { uint pkX = CommonTool.bytes2uint(gpkShare, 0, 32); uint pkY = CommonTool.bytes2uint(gpkShare, 32, 32); (x, y, success) = ICurve(round.curve).add(x, y, pkX, pkY); require(success == true, "Add failed"); } else { gpkShare = new bytes(64); } assembly { mstore(add(gpkShare, 32), x) } assembly { mstore(add(gpkShare, 64), y) } round.srcMap[txAddress].gpkShare = gpkShare; } } /// @notice function for verify sij to judge challenge /// @param d Dest /// @param destPk dest storeman pk /// @param polyCommit polyCommit of pki /// @param curve curve contract address function verifySij(GpkTypes.Dest storage d, bytes destPk, bytes polyCommit, address curve) public view returns(bool) { // check sij uint x; uint y; uint pcX; uint pcY; bool success; (x, y, success) = ICurve(curve).mulG(d.sij); if (success) { (pcX, pcY, success) = ICurve(curve).calPolyCommit(polyCommit, destPk); if (success && (x == pcX) && (y == pcY)) { // check enc uint iv = CommonTool.bytes2uint(d.encSij, 65, 16); bytes memory cipher; (cipher, success) = CommonTool.enc(bytes32(d.ephemPrivateKey), bytes32(iv), d.sij, destPk); if (success) { return CommonTool.cmpBytes(d.encSij, cipher); } } } return false; } /// @notice function for slash /// @param group storeman group /// @param curveIndex signature curve index /// @param slashType slash reason /// @param slashed slashed storeman /// @param parter negotiate parter /// @param toReset is reset immediately /// @param smg the storeman group admin contract function slash(GpkTypes.Group storage group, uint8 curveIndex, GpkTypes.SlashType slashType, address slashed, address parter, bool toReset, address smg) public { GpkTypes.Src storage src = group.roundMap[group.round][curveIndex].srcMap[slashed]; if (src.slashType == GpkTypes.SlashType.None) { group.roundMap[group.round][curveIndex].slashCount++; } if ((slashType == GpkTypes.SlashType.SijInvalid) || (slashType == GpkTypes.SlashType.CheckInvalid) || (src.slashType == GpkTypes.SlashType.None) || (src.slashType == GpkTypes.SlashType.Connive)) { src.slashType = slashType; } emit SlashLogger(group.groupId, uint8(slashType), slashed, parter, group.round, curveIndex); if (toReset) { uint[] memory ids = new uint[](1); ids[0] = group.indexMap[slashed]; uint8[] memory types = new uint8[](1); types[0] = uint8(slashType); bool isContinue = IStoremanGroup(smg).setInvalidSm(group.groupId, ids, types); reset(group, isContinue); } } /// @notice function for slash /// @param group storeman group /// @param curveIndex singnature curve index /// @param smg smg contract address function slashMulti(GpkTypes.Group storage group, uint8 curveIndex, address smg) public { GpkTypes.Round storage round = group.roundMap[group.round][curveIndex]; uint[] memory ids = new uint[](round.slashCount); uint8[] memory types = new uint8[](round.slashCount); uint slashCount = 0; for (uint i = 0; (i < group.smNumber) && (slashCount < round.slashCount); i++) { GpkTypes.Src storage src = round.srcMap[group.addrMap[i]]; if (src.slashType != GpkTypes.SlashType.None) { ids[slashCount] = i; types[slashCount] = uint8(src.slashType); slashCount++; } } bool isContinue = IStoremanGroup(smg).setInvalidSm(group.groupId, ids, types); reset(group, isContinue); } /// @notice function for reset protocol /// @param group storeman group /// @param isContinue is continue to next round function reset(GpkTypes.Group storage group, bool isContinue) public { GpkTypes.Round storage round = group.roundMap[group.round][0]; round.status = GpkTypes.GpkStatus.Close; round.statusTime = now; round = group.roundMap[group.round][1]; round.status = GpkTypes.GpkStatus.Close; round.statusTime = now; // clear data for (uint i = 0; i < group.smNumber; i++) { delete group.pkMap[group.addrMap[i]]; delete group.indexMap[group.addrMap[i]]; delete group.addrMap[i]; } group.smNumber = 0; if (isContinue) { emit ResetLogger(group.groupId, group.round); group.round++; } else { emit CloseLogger(group.groupId, group.round); } } }
contracts/gpk/GpkStorage.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.24; import "../components/BasicStorage.sol"; import "./lib/GpkTypes.sol"; contract GpkStorage is BasicStorage { /// smg instance address address public smg; /// gpk config address public cfg; /// groupId -> Group mapping(bytes32 => GpkTypes.Group) public groupMap; }
contracts/interfaces/IListGroup.sol
pragma solidity ^0.4.24; interface IListGroup { function addActiveGroup(bytes32 groupId, uint startTime, uint endTime) external; function getActiveGroupIds(uint day) external view returns (bytes32[]); function getTotalDeposit(uint day) external view returns(uint); function setTotalDeposit(uint day, uint value) external; function cleanExpiredGroup() external; function getDelegateQuitGroupId(address wkAddr, address deAddr) external view returns (bytes32 groupId, bytes32 nextGroupId); function getPartQuitGroupId(address wkAddr, address pnAddr) external view returns (bytes32 groupId, bytes32 nextGroupId); function setDelegateQuitGroupId(address wkAddr, address deAddr, bytes32 groupId, bytes32 nextGroupId)external; function setPartQuitGroupId(address wkAddr, address pnAddr, bytes32 groupId, bytes32 nextGroupId) external; }
contracts/interfaces/IWrappedNFT1155.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; interface IWrappedNFT1155 { function changeOwner(address _newOwner) external; function acceptOwnership() external; function transferOwner(address) external; function name() external view returns (string); function symbol() external view returns (string); function update(string, string) external; function burnBatch(address , uint256[] , uint256[] ) public; function mintBatch(address , uint256[] , uint256[] , bytes) public; }
contracts/components/BasicStorage.sol
pragma solidity ^0.4.24; import "../lib/BasicStorageLib.sol"; contract BasicStorage { /************************************************************ ** ** VARIABLES ** ************************************************************/ //// basic variables using BasicStorageLib for BasicStorageLib.UintData; using BasicStorageLib for BasicStorageLib.BoolData; using BasicStorageLib for BasicStorageLib.AddressData; using BasicStorageLib for BasicStorageLib.BytesData; using BasicStorageLib for BasicStorageLib.StringData; BasicStorageLib.UintData internal uintData; BasicStorageLib.BoolData internal boolData; BasicStorageLib.AddressData internal addressData; BasicStorageLib.BytesData internal bytesData; BasicStorageLib.StringData internal stringData; }
contracts/metric/MetricProxy.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; /** * Math operations with safety checks */ import "../components/Halt.sol"; import "../components/Admin.sol"; import "./MetricStorage.sol"; import "../components/Proxy.sol"; contract MetricProxy is MetricStorage, Halt, Proxy { ///@dev update the address of MetricDelegate contract ///@param impl the address of the new MetricDelegate contract function upgradeTo(address impl) public onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require(impl != _implementation, "Cannot upgrade to the same implementation"); _implementation = impl; emit Upgraded(impl); } }
contracts/test/FakeSmg.sol
pragma solidity ^0.4.24; import '../storemanGroupAdmin/StoremanType.sol'; contract FakeSmg { /* * * VARIABLES * */ uint constant SelectedSMNumber = 4; uint constant ThresholdNumber = 3; string constant GroupIdStr = "0000000000000000000000000000000000000031353839393533323738313235"; string constant GroupIdStr1 = "0000000000000000000000000000000000000031353839393533323738313236"; string constant EnodeIdStr = "0000000000000000000000000000000000000000000000000000000000000001"; string constant bytestr = "bytes"; string constant gpk1Str = "82e5d4ad633e9e028b283e52338e4fe4c5467091fd4f5d9aec74cb78c25738be1154a9b1cff44b7fe935e774da7a9fad873b76323573138bc361a9cfdb6a20d2"; string constant gpk2Str = "1761e90a6287d8e771373074626befaf4a46e6e3a2d45f8b7a2ec5361f1de7a102d43cd0d14e5a438d754c01d0d94cf2a8ff8fd9df49c9f7291975c831bcb983"; string constant gpkShare1Str = "f716e789cd79d106343b8e9c3ac494865d02241337cf6ce8df4df6548ec1eccc900963c639664b1667df09d322a8e5c8a9185a09742f96b204b4fcc59dae7fab"; string constant gpkShare2Str = "17a4f5c4add16108a4ab16fc1635635af0df9798176459ca3cd58a15ceb64d4808651a691e5f89ed012ee076bc39bff193064b852ce11741f0110a81c6d876d7"; bytes32 grpId; // string[4] Pks = ["0425fa6a4190ddc87d9f9dd986726cafb901e15c21aafd2ed729efed1200c73de89f1657726631d29733f4565a97dc00200b772b4bc2f123a01e582e7e56b80cf8", // "04be3b7fd88613dc272a36f4de570297f5f33b87c26de3060ad04e2ea697e13125a2454acd296e1879a7ddd0084d9e4e724fca9ef610b21420978476e2632a1782", // "0495e8fd461c37f1db5da62bfbee2ad305d77e57fbef917ec8109e6425e942fb60ddc28b1edfdbcda1aa5ace3160b458b9d3d5b1fe306b4d09a030302a08e2db93", // "04ccd16e96a70a5b496ff1cec869902b6a8ffa00715897937518f1c9299726f7090bc36cc23c1d028087eb0988c779663e996391f290631317fc22f84fa9bf2467"]; string[4] Pks = ["25fa6a4190ddc87d9f9dd986726cafb901e15c21aafd2ed729efed1200c73de89f1657726631d29733f4565a97dc00200b772b4bc2f123a01e582e7e56b80cf8", "be3b7fd88613dc272a36f4de570297f5f33b87c26de3060ad04e2ea697e13125a2454acd296e1879a7ddd0084d9e4e724fca9ef610b21420978476e2632a1782", "95e8fd461c37f1db5da62bfbee2ad305d77e57fbef917ec8109e6425e942fb60ddc28b1edfdbcda1aa5ace3160b458b9d3d5b1fe306b4d09a030302a08e2db93", "ccd16e96a70a5b496ff1cec869902b6a8ffa00715897937518f1c9299726f7090bc36cc23c1d028087eb0988c779663e996391f290631317fc22f84fa9bf2467"]; address constant ADD_0 = 0x0000000000000000000000000000000000000000; address constant ADD_LEADER= 0x2d0e7c0813a51d3bd1d08246af2a8a7a57d8922e; address public leaderAdd; // groupId=>index=>pk mapping(bytes32 => mapping(uint8 => bytes)) mapSmgInfo; constructor() public { grpId = bytesToBytes32(fromHex(GroupIdStr), 0); for (uint i = 0; i < Pks.length; i++) { mapSmgInfo[grpId][uint8(i)] = fromHex(Pks[i]); } grpId = bytesToBytes32(fromHex(GroupIdStr1), 0); for (uint j = 0; j < Pks.length; j++) { mapSmgInfo[grpId][uint8(j)] = fromHex(Pks[j]); } } /* * * FUNCTIONS * */ function getSelectedSmNumber(bytes32 groupId) external pure returns (uint number){ return SelectedSMNumber; } function getThresholdByGrpId(bytes32 groupId) external pure returns (uint){ return ThresholdNumber; } function getSelectedSmInfo(bytes32 groupId, uint index) external view returns (address txAddress, bytes pk, bytes enodeId){ (txAddress,pk,enodeId) = (leaderAdd, mapSmgInfo[groupId][uint8(index)], fromHex(EnodeIdStr)); } function getStoremanInfo(address wkAddress) external pure returns( bytes32 groupId, bytes32 nextGroupId) { return (bytesToBytes32(fromHex(GroupIdStr),0),bytesToBytes32(fromHex(GroupIdStr1),0)); } function getStoremanGroupInfo(bytes32 id) external pure returns(bytes32 groupId, StoremanType.GroupStatus status, uint deposit, uint whiteCount, uint memberCount, uint startTime, uint endTime){ return (bytesToBytes32(fromHex(GroupIdStr),0),StoremanType.GroupStatus.ready,uint(0),uint(0),uint(0),uint(0),uint(0)); } function getStoremanGroupConfig(bytes32 id) external pure returns(bytes32 groupId, uint8 status, uint deposit, uint chain1, uint chain2, uint curve1, uint curve2, bytes gpk1, bytes gpk2, uint startTime, uint endTime){ return (bytesToBytes32(fromHex(GroupIdStr),0),0,0,0,0,0x00,0x01,fromHex(gpk1Str),fromHex(gpk2Str),0,0); } function getGpkShare(bytes32 groupId, uint index) external pure returns(bytes gpkShare1, bytes gpkShare2){ return (fromHex(gpkShare1Str),fromHex(gpkShare2Str)); } function setLeader(address leader) external{ leaderAdd = leader; } function bytesToBytes32(bytes b, uint offset) internal pure returns (bytes32) { bytes32 out; for (uint i = 0; i < 32; i++) { out |= bytes32(b[offset + i] & 0xFF) >> (i * 8); } return out; } // Convert an hexadecimal character to their value function fromHexChar(uint c) public pure returns (uint) { if (byte(c) >= byte('0') && byte(c) <= byte('9')) { return c - uint(byte('0')); } if (byte(c) >= byte('a') && byte(c) <= byte('f')) { return 10 + c - uint(byte('a')); } if (byte(c) >= byte('A') && byte(c) <= byte('F')) { return 10 + c - uint(byte('A')); } return uint(0); } // Convert an hexadecimal string to raw bytes function fromHex(string s) public pure returns (bytes) { bytes memory ss = bytes(s); require(ss.length % 2 == 0); // length must be even bytes memory r = new bytes(ss.length / 2); for (uint i = 0; i < ss.length / 2; ++i) { r[i] = byte(fromHexChar(uint(ss[2 * i])) * 16 + fromHexChar(uint(ss[2 * i + 1]))); } return r; } function recordSmSlash(address wk) external{} }
contracts/lib/BasicStorageLib.sol
pragma solidity ^0.4.24; library BasicStorageLib { struct UintData { mapping(bytes => mapping(bytes => uint)) _storage; } struct BoolData { mapping(bytes => mapping(bytes => bool)) _storage; } struct AddressData { mapping(bytes => mapping(bytes => address)) _storage; } struct BytesData { mapping(bytes => mapping(bytes => bytes)) _storage; } struct StringData { mapping(bytes => mapping(bytes => string)) _storage; } /* uintStorage */ function setStorage(UintData storage self, bytes memory key, bytes memory innerKey, uint value) internal { self._storage[key][innerKey] = value; } function getStorage(UintData storage self, bytes memory key, bytes memory innerKey) internal view returns (uint) { return self._storage[key][innerKey]; } function delStorage(UintData storage self, bytes memory key, bytes memory innerKey) internal { delete self._storage[key][innerKey]; } /* boolStorage */ function setStorage(BoolData storage self, bytes memory key, bytes memory innerKey, bool value) internal { self._storage[key][innerKey] = value; } function getStorage(BoolData storage self, bytes memory key, bytes memory innerKey) internal view returns (bool) { return self._storage[key][innerKey]; } function delStorage(BoolData storage self, bytes memory key, bytes memory innerKey) internal { delete self._storage[key][innerKey]; } /* addressStorage */ function setStorage(AddressData storage self, bytes memory key, bytes memory innerKey, address value) internal { self._storage[key][innerKey] = value; } function getStorage(AddressData storage self, bytes memory key, bytes memory innerKey) internal view returns (address) { return self._storage[key][innerKey]; } function delStorage(AddressData storage self, bytes memory key, bytes memory innerKey) internal { delete self._storage[key][innerKey]; } /* bytesStorage */ function setStorage(BytesData storage self, bytes memory key, bytes memory innerKey, bytes memory value) internal { self._storage[key][innerKey] = value; } function getStorage(BytesData storage self, bytes memory key, bytes memory innerKey) internal view returns (bytes memory) { return self._storage[key][innerKey]; } function delStorage(BytesData storage self, bytes memory key, bytes memory innerKey) internal { delete self._storage[key][innerKey]; } /* stringStorage */ function setStorage(StringData storage self, bytes memory key, bytes memory innerKey, string memory value) internal { self._storage[key][innerKey] = value; } function getStorage(StringData storage self, bytes memory key, bytes memory innerKey) internal view returns (string memory) { return self._storage[key][innerKey]; } function delStorage(StringData storage self, bytes memory key, bytes memory innerKey) internal { delete self._storage[key][innerKey]; } }
openzeppelin-eth/contracts/token/ERC721/IERC721Metadata.sol
pragma solidity ^0.4.24; import "../../zos-lib/Initializable.sol"; import "./IERC721.sol"; /** * @title ERC-721 Non-Fungible Token Standard, optional metadata extension * @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721Metadata is Initializable, IERC721 { function name() external view returns (string); function symbol() external view returns (string); function tokenURI(uint256 tokenId) public view returns (string); }
contracts/crossApproach/lib/RapidityTxLib.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; library RapidityTxLib { /** * * ENUMS * */ /// @notice tx info status /// @notice uninitialized,Redeemed enum TxStatus {None, Redeemed} /** * * STRUCTURES * */ struct Data { /// @notice mapping of uniqueID to TxStatus -- uniqueID->TxStatus mapping(bytes32 => TxStatus) mapTxStatus; } /** * * MANIPULATIONS * */ /// @notice add user transaction info /// @param uniqueID Rapidity random number function addRapidityTx(Data storage self, bytes32 uniqueID) internal { TxStatus status = self.mapTxStatus[uniqueID]; require(status == TxStatus.None, "Rapidity tx exists"); self.mapTxStatus[uniqueID] = TxStatus.Redeemed; } }
contracts/components/StandardToken.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; import "./WRC20Protocol.sol"; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; contract StandardToken is WRC20Protocol { using SafeMath for uint; /** * @dev Fix for the ERC20 short address attack. */ modifier onlyPayloadSize(uint size) { require(msg.data.length >= size + 4, "Payload size is incorrect"); _; } function transfer(address _to, uint _value) public onlyPayloadSize(2 * 32) returns (bool success) { balances[msg.sender] = balances[msg.sender].sub(_value); balances[_to] = balances[_to].add(_value); emit Transfer(msg.sender, _to, _value); return true; } function transferFrom(address _from, address _to, uint _value) public onlyPayloadSize(3 * 32) returns (bool success) { balances[_to] = balances[_to].add(_value); balances[_from] = balances[_from].sub(_value); allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value); emit Transfer(_from, _to, _value); return true; } function balanceOf(address _owner) public view returns (uint balance) { return balances[_owner]; } function approve(address _spender, uint _value) public onlyPayloadSize(2 * 32) returns (bool success) { // To change the approve amount you first have to reduce the addresses` // allowance to zero by calling `approve(_spender, 0)` if it is not // already 0 to mitigate the race condition described here: // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 require((_value == 0) || (allowed[msg.sender][_spender] == 0), "Not permitted"); allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } function allowance(address _owner, address _spender) public view returns (uint remaining) { return allowed[_owner][_spender]; } }
contracts/schnorr/Bn128SchnorrVerifier.sol
pragma solidity ^0.4.24; import "./Bn128.sol"; contract Bn128SchnorrVerifier is Bn128 { struct Point { uint256 x; uint256 y; } struct Verification { Point groupKey; Point randomPoint; uint256 signature; bytes32 message; uint256 _hash; Point _left; Point _right; } function h(bytes32 m, uint256 a, uint256 b) public pure returns (uint256) { return uint256(sha256(abi.encodePacked(m, a, b))); } // function cmul(Point p, uint256 scalar) public pure returns (uint256, uint256) { function cmul(uint256 x, uint256 y, uint256 scalar) public view returns (uint256, uint256) { return ecmul(x, y, scalar); } function sg(uint256 sig_s) public view returns (uint256, uint256) { return ecmul(getGx(), getGy(), sig_s); } // function cadd(Point a, Point b) public pure returns (uint256, uint256) { function cadd(uint256 ax, uint256 ay, uint256 bx, uint256 by) public view returns (uint256, uint256) { return ecadd(ax, ay, bx, by); } function verify(bytes32 signature, bytes32 groupKeyX, bytes32 groupKeyY, bytes32 randomPointX, bytes32 randomPointY, bytes32 message) public view returns(bool) { bool flag = false; Verification memory state; state.signature = uint256(signature); state.groupKey.x = uint256(groupKeyX); state.groupKey.y = uint256(groupKeyY); state.randomPoint.x = uint256(randomPointX); state.randomPoint.y = uint256(randomPointY); state.message = message; state._hash = h(state.message, state.randomPoint.x, state.randomPoint.y); /// change to bn256 range. state._hash = uint256(state._hash).mod(getOrder()); (state._left.x, state._left.y) = sg(state.signature); Point memory rightPart; (rightPart.x, rightPart.y) = cmul(state.groupKey.x, state.groupKey.y, state._hash); (state._right.x, state._right.y) = cadd(state.randomPoint.x, state.randomPoint.y, rightPart.x, rightPart.y); flag = state._left.x == state._right.x && state._left.y == state._right.y; return flag; } }
contracts/quota/QuotaProxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; /** * Math operations with safety checks */ import "../components/Halt.sol"; import "./QuotaStorage.sol"; import "../components/Proxy.sol"; contract QuotaProxy is QuotaStorage, Halt, Proxy { ///@dev update the address of HTLCDelegate contract ///@param impl the address of the new HTLCDelegate contract function upgradeTo(address impl) public onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require( impl != _implementation, "Cannot upgrade to the same implementation" ); _implementation = impl; emit Upgraded(impl); } }
contracts/test/MappingNftToken.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.4.26; import 'openzeppelin-eth/contracts/ownership/Ownable.sol'; import 'openzeppelin-eth/contracts/token/ERC721/ERC721Full.sol'; /** * @notice This is the template for all NFT contract. */ contract MappingNftToken is ERC721Full, Ownable { using SafeMath for uint; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * The defaut value of {decimals} is 18. To select a different value for * {decimals} you should overload it. * * All three of these values are immutable: they can only be set once during * construction. */ constructor( string name_, string symbol_ ) public { _name = name_; _symbol = symbol_; Ownable.initialize(msg.sender); ERC721.initialize(); ERC721Enumerable.initialize(); ERC721Metadata.initialize(name_, symbol_); } /**************************************************************************** ** ** MANIPULATIONS of mapping token ** ****************************************************************************/ /// @notice Create token /// @dev Create token /// @param account_ Address will receive token /// @param nftID ID of token to be minted function mint(address account_, uint256 nftID) external onlyOwner { _mint(account_, nftID); } /// @notice Burn token /// @dev Burn token /// @param account_ Address of whose token will be burnt /// @param nftID ID of token to be burnt function burn(address account_, uint256 nftID) external onlyOwner { _burn(account_, nftID); } /// @notice update token name, symbol /// @dev update token name, symbol /// @param name_ token new name /// @param symbol_ token new symbol function update(string name_, string symbol_) external onlyOwner { _name = name_; _symbol = symbol_; } function transferOwner(address newOwner_) public onlyOwner { Ownable.transferOwnership(newOwner_); } // mint supprt data function mint(address account_, uint256 nftID, bytes data) external onlyOwner { _mint(account_, nftID); } function burnBatch(address account_, uint256[] nftIDs) external onlyOwner { for(uint i = 0; i < nftIDs.length; ++i) { _burn(account_, nftIDs[i]); } } function mintBatch(address account_, uint256[] nftIDs, bytes data) external onlyOwner { for(uint i = 0; i < nftIDs.length; ++i) { _mint(account_, nftIDs[i]); } } }
contracts/quota/QuotaStorageV2.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; import "./QuotaProxy.sol"; /** * Math operations with safety checks */ contract QuotaStorageV2 is QuotaProxy { /// @dev mapping: tokenId => storemanPk => Quota mapping(uint => mapping(bytes32 => Quota)) v2QuotaMap; /// @dev mapping: storemanPk => tokenIndex => tokenId, tokenIndex:0,1,2,3... mapping(bytes32 => mapping(uint => uint)) v2TokensMap; /// @dev mapping: storemanPk => token count mapping(bytes32 => uint) v2TokenCountMap; /// upgrade version uint public version; }
contracts/config/ConfigDelegate.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../components/Halt.sol"; import "../components/Admin.sol"; import "./ConfigStorage.sol"; contract ConfigDelegate is ConfigStorage, Halt , Admin{ /// @notice function for set smg contract address /// @param curveId curve id array /// @param curveAddress curve contract address array function setCurve(uint8[] curveId, address[] curveAddress) external onlyAdmin { uint8 length = uint8(curveId.length); require((length > 0) && (length == curveAddress.length), "Mismatched length"); for (uint8 i = 0; i < length; i++) { curves[curveId[i]] = curveAddress[i]; } } function getCurve(uint8 curveId) external view returns(address){ require(curves[curveId] != address(0), "No curve"); return curves[curveId]; } function() public payable { revert("Not support"); } }
contracts/quota/QuotaDelegate.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; /** * Math operations with safety checks */ import "./QuotaStorageV2.sol"; import "../interfaces/IOracle.sol"; interface _ITokenManager { function getAncestorSymbol(uint id) external view returns (string symbol, uint8 decimals); } interface _IStoremanGroup { function getDeposit(bytes32 id) external view returns(uint deposit); } interface IDebtOracle { function isDebtClean(bytes32 storemanGroupId) external view returns (bool); } contract QuotaDelegate is QuotaStorageV2 { event AssetTransfered(bytes32 indexed srcStoremanGroupId, bytes32 indexed dstStoremanGroupId, uint tokenId, uint value); event DebtReceived(bytes32 indexed srcStoremanGroupId, bytes32 indexed dstStoremanGroupId, uint tokenId, uint value); modifier checkMinValue(uint tokenId, uint value) { if (fastCrossMinValue > 0) { string memory symbol; uint decimals; (symbol, decimals) = getTokenAncestorInfo(tokenId); uint price = getPrice(symbol); if (price > 0) { uint count = fastCrossMinValue.mul(10**decimals).div(price); require(value >= count, "value too small"); } } _; } /// @notice config params for owner /// @param _priceOracleAddr token price oracle contract address /// @param _htlcAddr HTLC contract address /// @param _depositOracleAddr deposit oracle address, storemanAdmin or oracle /// @param _depositRate deposit rate value, 15000 means 150% /// @param _depositTokenSymbol deposit token symbol, default is WAN /// @param _tokenManagerAddress token manager contract address function config( address _priceOracleAddr, address _htlcAddr, address _fastHtlcAddr, address _depositOracleAddr, address _tokenManagerAddress, uint _depositRate, string _depositTokenSymbol ) external onlyOwner { priceOracleAddress = _priceOracleAddr; htlcGroupMap[_htlcAddr] = true; htlcGroupMap[_fastHtlcAddr] = true; depositOracleAddress = _depositOracleAddr; depositRate = _depositRate; depositTokenSymbol = _depositTokenSymbol; tokenManagerAddress = _tokenManagerAddress; } function setDebtOracle(address oracle) external onlyOwner { debtOracleAddress = oracle; } function setFastCrossMinValue(uint value) external onlyOwner { fastCrossMinValue = value; } /// @notice get asset of storeman, tokenId /// @param tokenId tokenPairId of crosschain /// @param storemanGroupId PK of source storeman group function getAsset(uint tokenId, bytes32 storemanGroupId) public view returns (uint asset, uint asset_receivable, uint asset_payable) { uint tokenKey = getTokenKey(tokenId); Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; return (quota._asset, quota.asset_receivable, quota.asset_payable); } /// @notice get debt of storeman, tokenId /// @param tokenId tokenPairId of crosschain /// @param storemanGroupId PK of source storeman group function getDebt(uint tokenId, bytes32 storemanGroupId) public view returns (uint debt, uint debt_receivable, uint debt_payable) { uint tokenKey = getTokenKey(tokenId); Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; return (quota._debt, quota.debt_receivable, quota.debt_payable); } /// @notice get debt clean state of storeman /// @param storemanGroupId PK of source storeman group function isDebtClean(bytes32 storemanGroupId) external view returns (bool) { uint tokenCount = v2TokenCountMap[storemanGroupId]; if (tokenCount == 0) { if (debtOracleAddress == address(0)) { return true; } else { IDebtOracle debtOracle = IDebtOracle(debtOracleAddress); return debtOracle.isDebtClean(storemanGroupId); } } for (uint i = 0; i < tokenCount; i++) { uint id = v2TokensMap[storemanGroupId][i]; Quota storage src = v2QuotaMap[id][storemanGroupId]; if (src._debt > 0 || src.debt_payable > 0 || src.debt_receivable > 0) { return false; } if (src._asset > 0 || src.asset_payable > 0 || src.asset_receivable > 0) { return false; } } return true; } /// @dev get minimize token count for fast cross chain function getFastMinCount(uint tokenId) public view returns (uint, string, uint, uint, uint) { if (fastCrossMinValue == 0) { return (0, "", 0, 0, 0); } string memory symbol; uint decimals; (symbol, decimals) = getTokenAncestorInfo(tokenId); uint price = getPrice(symbol); uint count = 0; if (price > 0) { count = fastCrossMinValue.mul(10**decimals).div(price); } return (fastCrossMinValue, symbol, decimals, price, count); } /** New Cross Chain Interface*/ function userLock(uint tokenId, bytes32 storemanGroupId, uint value) public onlyHtlc checkMinValue(tokenId, value) { uint tokenKey = getTokenKey(tokenId); Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; if (!quota._active) { quota._active = true; v2TokensMap[storemanGroupId][v2TokenCountMap[storemanGroupId]] = tokenKey; v2TokenCountMap[storemanGroupId] = v2TokenCountMap[storemanGroupId] .add(1); } quota._asset = quota._asset.add(value); } function userBurn(uint tokenId, bytes32 storemanGroupId, uint value) external onlyHtlc checkMinValue(tokenId, value) { uint tokenKey = getTokenKey(tokenId); Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; quota._debt = quota._debt.sub(value); } function smgRelease(uint tokenId, bytes32 storemanGroupId, uint value) external onlyHtlc { uint tokenKey = getTokenKey(tokenId); Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; quota._asset = quota._asset.sub(value); } function smgMint(uint tokenId, bytes32 storemanGroupId, uint value) public onlyHtlc { uint tokenKey = getTokenKey(tokenId); Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; if (!quota._active) { quota._active = true; v2TokensMap[storemanGroupId][v2TokenCountMap[storemanGroupId]] = tokenKey; v2TokenCountMap[storemanGroupId] = v2TokenCountMap[storemanGroupId] .add(1); } quota._debt = quota._debt.add(value); } function adjustSmgQuota(bytes32 storemanGroupId, uint tokenKey, uint asset, uint debt) external onlyOwner { Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; quota._asset = asset; quota._debt = debt; } function upgrade(bytes32[] storemanGroupIdArray) external onlyOwner { require(version < 2, "Can upgrade again."); version = 2; //upgraded v2 uint length = storemanGroupIdArray.length; for (uint m = 0; m < length; m++) { bytes32 storemanGroupId = storemanGroupIdArray[m]; uint tokenCount = storemanTokenCountMap[storemanGroupId]; for (uint i = 0; i < tokenCount; i++) { uint id = storemanTokensMap[storemanGroupId][i]; uint tokenKey = getTokenKey(id); Quota storage src = quotaMap[id][storemanGroupId]; uint debt = src._debt; if (debt > 0) { Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; if (!quota._active) { quota._active = true; v2TokensMap[storemanGroupId][v2TokenCountMap[storemanGroupId]] = tokenKey; v2TokenCountMap[storemanGroupId] = v2TokenCountMap[storemanGroupId] .add(1); } quota._debt = quota._debt.add(debt); } uint asset = src._asset; if (asset > 0) { Quota storage quota2 = v2QuotaMap[tokenKey][storemanGroupId]; if (!quota2._active) { quota2._active = true; v2TokensMap[storemanGroupId][v2TokenCountMap[storemanGroupId]] = tokenKey; v2TokenCountMap[storemanGroupId] = v2TokenCountMap[storemanGroupId] .add(1); } quota2._asset = quota2._asset.add(asset); } } } } function transferAsset( bytes32 srcStoremanGroupId, bytes32 dstStoremanGroupId ) external onlyHtlc { uint tokenCount = v2TokenCountMap[srcStoremanGroupId]; for (uint i = 0; i < tokenCount; i++) { uint id = v2TokensMap[srcStoremanGroupId][i]; Quota storage src = v2QuotaMap[id][srcStoremanGroupId]; if (src._asset == 0) { continue; } Quota storage dst = v2QuotaMap[id][dstStoremanGroupId]; if (!dst._active) { dst._active = true; v2TokensMap[dstStoremanGroupId][v2TokenCountMap[dstStoremanGroupId]] = id; v2TokenCountMap[dstStoremanGroupId] = v2TokenCountMap[dstStoremanGroupId] .add(1); } /// Adjust quota record dst._asset = dst._asset.add(src._asset); emit AssetTransfered(srcStoremanGroupId, dstStoremanGroupId, id, src._asset); src.asset_payable = 0; src._asset = 0; } } function receiveDebt( bytes32 srcStoremanGroupId, bytes32 dstStoremanGroupId ) external onlyHtlc { uint tokenCount = v2TokenCountMap[srcStoremanGroupId]; for (uint i = 0; i < tokenCount; i++) { uint id = v2TokensMap[srcStoremanGroupId][i]; Quota storage src = v2QuotaMap[id][srcStoremanGroupId]; if (src._debt == 0) { continue; } Quota storage dst = v2QuotaMap[id][dstStoremanGroupId]; if (!dst._active) { dst._active = true; v2TokensMap[dstStoremanGroupId][v2TokenCountMap[dstStoremanGroupId]] = id; v2TokenCountMap[dstStoremanGroupId] = v2TokenCountMap[dstStoremanGroupId] .add(1); } /// Adjust quota record dst._debt = dst._debt.add(src._debt); emit DebtReceived(srcStoremanGroupId, dstStoremanGroupId, id, src._debt); src.debt_payable = 0; src._debt = 0; } } function getQuotaMap(uint tokenKey, bytes32 storemanGroupId) public view returns (uint debt_receivable, uint debt_payable, uint _debt, uint asset_receivable, uint asset_payable, uint _asset, bool _active) { Quota storage quota = v2QuotaMap[tokenKey][storemanGroupId]; return (quota.debt_receivable, quota.debt_payable, quota._debt, quota.asset_receivable, quota.asset_payable, quota._asset, quota._active); } function getTokenKey(uint tokenId) public view returns (uint) { string memory symbol; uint decimals; (symbol, decimals) = getTokenAncestorInfo(tokenId); uint tokenKey = uint(keccak256(abi.encodePacked(symbol, decimals))); return tokenKey; } function getTokenCount(bytes32 storemanGroupId) public view returns (uint) { return v2TokenCountMap[storemanGroupId]; } function getTokenId(bytes32 storemanGroupId, uint index) public view returns (uint) { return v2TokensMap[storemanGroupId][index]; } function getTokenQuota(string ancestorSymbol, uint decimals, bytes32 storemanGroupId) public view returns (uint debt_receivable, uint debt_payable, uint _debt, uint asset_receivable, uint asset_payable, uint _asset, bool _active) { uint tokenKey = uint(keccak256(abi.encodePacked(ancestorSymbol, decimals))); return getQuotaMap(tokenKey, storemanGroupId); } function getOldQuotaMap(uint tokenId, bytes32 storemanGroupId) public view returns (uint debt_receivable, uint debt_payable, uint _debt, uint asset_receivable, uint asset_payable, uint _asset, bool _active) { Quota storage quota = quotaMap[tokenId][storemanGroupId]; return (quota.debt_receivable, quota.debt_payable, quota._debt, quota.asset_receivable, quota.asset_payable, quota._asset, quota._active); } // ----------- Private Functions --------------- function getTokenAncestorInfo(uint tokenId) private view returns (string ancestorSymbol, uint decimals) { _ITokenManager tokenManager = _ITokenManager(tokenManagerAddress); (ancestorSymbol,decimals) = tokenManager.getAncestorSymbol(tokenId); } function stringToBytes32(string memory source) public pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } function getPrice(string symbol) private view returns (uint price) { IOracle oracle = IOracle(priceOracleAddress); price = oracle.getValue(stringToBytes32(symbol)); } }
contracts/components/Owned.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; /// @dev `Owned` is a base level contract that assigns an `owner` that can be /// later changed contract Owned { event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /// @dev `owner` is the only address that can call a function with this /// modifier modifier onlyOwner() { require(msg.sender == owner, "Not owner"); _; } address public owner; /// @notice The Constructor assigns the message sender to be `owner` constructor() public { owner = msg.sender; } address public newOwner; function transferOwner(address _newOwner) public onlyOwner { require(_newOwner != address(0), "New owner is the zero address"); emit OwnershipTransferred(owner, _newOwner); owner = _newOwner; } /// @notice `owner` can step down and assign some other address to this role /// @param _newOwner The address of the new owner. 0x0 can be used to create /// an unowned neutral vault, however that cannot be undone function changeOwner(address _newOwner) public onlyOwner { newOwner = _newOwner; } function acceptOwnership() public { if (msg.sender == newOwner) { owner = newOwner; } } function renounceOwnership() public onlyOwner { owner = address(0); } }
contracts/components/Halt.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; import './Owned.sol'; contract Halt is Owned { bool public halted = false; modifier notHalted() { require(!halted, "Smart contract is halted"); _; } modifier isHalted() { require(halted, "Smart contract is not halted"); _; } /// @notice function Emergency situation that requires /// @notice contribution period to stop or not. function setHalt(bool halt) public onlyOwner { halted = halt; } }
openzeppelin-eth/contracts/token/ERC721/ERC721.sol
pragma solidity ^0.4.24; import "../../zos-lib/Initializable.sol"; import "./IERC721.sol"; import "./IERC721Receiver.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; import "../../introspection/ERC165.sol"; /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721 is Initializable, ERC165, IERC721 { using SafeMath for uint256; using Address for address; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from token ID to owner mapping (uint256 => address) private _tokenOwner; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to number of owned token mapping (address => uint256) private _ownedTokensCount; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; /* * 0x80ac58cd === * bytes4(keccak256('balanceOf(address)')) ^ * bytes4(keccak256('ownerOf(uint256)')) ^ * bytes4(keccak256('approve(address,uint256)')) ^ * bytes4(keccak256('getApproved(uint256)')) ^ * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ * bytes4(keccak256('isApprovedForAll(address,address)')) ^ * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) */ function initialize() public initializer { ERC165.initialize(); // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_InterfaceId_ERC721); } function _hasBeenInitialized() internal view returns (bool) { return supportsInterface(_InterfaceId_ERC721); } /** * @dev Gets the balance of the specified address * @param owner address to query the balance of * @return uint256 representing the amount owned by the passed address */ function balanceOf(address owner) public view returns (uint256) { require(owner != address(0)); return _ownedTokensCount[owner]; } /** * @dev Gets the owner of the specified token ID * @param tokenId uint256 ID of the token to query the owner of * @return owner address currently marked as the owner of the given token ID */ function ownerOf(uint256 tokenId) public view returns (address) { address owner = _tokenOwner[tokenId]; require(owner != address(0)); return owner; } /** * @dev Approves another address to transfer the given token ID * The zero address indicates there is no approved address. * There can only be one approved address per token at a given time. * Can only be called by the token owner or an approved operator. * @param to address to be approved for the given token ID * @param tokenId uint256 ID of the token to be approved */ function approve(address to, uint256 tokenId) public { address owner = ownerOf(tokenId); require(to != owner); require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Gets the approved address for a token ID, or zero if no address set * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to query the approval of * @return address currently approved for the given token ID */ function getApproved(uint256 tokenId) public view returns (address) { require(_exists(tokenId)); return _tokenApprovals[tokenId]; } /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf * @param to operator address to set the approval * @param approved representing the status of the approval to be set */ function setApprovalForAll(address to, bool approved) public { require(to != msg.sender); _operatorApprovals[msg.sender][to] = approved; emit ApprovalForAll(msg.sender, to, approved); } /** * @dev Tells whether an operator is approved by a given owner * @param owner owner address which you want to query the approval of * @param operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll( address owner, address operator ) public view returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Transfers the ownership of a given token ID to another address * Usage of this method is discouraged, use `safeTransferFrom` whenever possible * Requires the msg sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function transferFrom( address from, address to, uint256 tokenId ) public { require(_isApprovedOrOwner(msg.sender, tokenId)); require(to != address(0)); _clearApproval(from, tokenId); _removeTokenFrom(from, tokenId); _addTokenTo(to, tokenId); emit Transfer(from, to, tokenId); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * * Requires the msg sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function safeTransferFrom( address from, address to, uint256 tokenId ) public { // solium-disable-next-line arg-overflow safeTransferFrom(from, to, tokenId, ""); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes _data ) public { transferFrom(from, to, tokenId); // solium-disable-next-line arg-overflow require(_checkAndCallSafeTransfer(from, to, tokenId, _data)); } /** * @dev Returns whether the specified token exists * @param tokenId uint256 ID of the token to query the existence of * @return whether the token exists */ function _exists(uint256 tokenId) internal view returns (bool) { address owner = _tokenOwner[tokenId]; return owner != address(0); } /** * @dev Returns whether the given spender can transfer a given token ID * @param spender address of the spender to query * @param tokenId uint256 ID of the token to be transferred * @return bool whether the msg.sender is approved for the given token ID, * is an operator of the owner, or is the owner of the token */ function _isApprovedOrOwner( address spender, uint256 tokenId ) internal view returns (bool) { address owner = ownerOf(tokenId); // Disable solium check because of // https://github.com/duaraghav8/Solium/issues/175 // solium-disable-next-line operator-whitespace return ( spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender) ); } /** * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted by the msg.sender */ function _mint(address to, uint256 tokenId) internal { require(to != address(0)); _addTokenTo(to, tokenId); emit Transfer(address(0), to, tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * @param tokenId uint256 ID of the token being burned by the msg.sender */ function _burn(address owner, uint256 tokenId) internal { _clearApproval(owner, tokenId); _removeTokenFrom(owner, tokenId); emit Transfer(owner, address(0), tokenId); } /** * @dev Internal function to clear current approval of a given token ID * Reverts if the given address is not indeed the owner of the token * @param owner owner of the token * @param tokenId uint256 ID of the token to be transferred */ function _clearApproval(address owner, uint256 tokenId) internal { require(ownerOf(tokenId) == owner); if (_tokenApprovals[tokenId] != address(0)) { _tokenApprovals[tokenId] = address(0); } } /** * @dev Internal function to add a token ID to the list of a given address * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenTo(address to, uint256 tokenId) internal { require(_tokenOwner[tokenId] == address(0)); _tokenOwner[tokenId] = to; _ownedTokensCount[to] = _ownedTokensCount[to].add(1); } /** * @dev Internal function to remove a token ID from the list of a given address * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFrom(address from, uint256 tokenId) internal { require(ownerOf(tokenId) == from); _ownedTokensCount[from] = _ownedTokensCount[from].sub(1); _tokenOwner[tokenId] = address(0); } /** * @dev Internal function to invoke `onERC721Received` on a target address * The call is not executed if the target address is not a contract * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return whether the call correctly returned the expected magic value */ function _checkAndCallSafeTransfer( address from, address to, uint256 tokenId, bytes _data ) internal returns (bool) { if (!to.isContract()) { return true; } bytes4 retval = IERC721Receiver(to).onERC721Received( msg.sender, from, tokenId, _data); return (retval == _ERC721_RECEIVED); } uint256[50] private ______gap; }
contracts/test/TestQuotaHelper.sol
pragma solidity 0.4.26; import "../interfaces/ITokenManager.sol"; contract TestQuotaHelper { mapping(bytes32 => uint256) priceMap; constructor() public { priceMap[stringToBytes32("BTC")] = 998000000000; priceMap[stringToBytes32("ETH")] = 24500000000; priceMap[stringToBytes32("WAN")] = 21240000; } function stringToBytes32(string memory source) public pure returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } function getValue(bytes32 key) public view returns (uint256 price) { return priceMap[key]; } function setValue(string key, uint256 value) public { priceMap[stringToBytes32(key)] = value; } function getStoremanGroupConfig(bytes32 storemanGroupId) external pure returns ( bytes32 groupId, uint256 status, uint256 deposit, uint256 chain1, uint256 chain2, uint256 curve1, uint256 curve2, bytes gpk1, bytes gpk2, uint256 startTime, uint256 endTime ) { if (storemanGroupId == keccak256("storeman1")) { deposit = 1000 ether; } if (storemanGroupId == keccak256("storeman2")) { deposit = 1000 ether; } if (storemanGroupId == keccak256("storeman3")) { deposit = 1000 ether; } if (storemanGroupId == keccak256("storeman4")) { deposit = 1000 ether; } } function getDeposit(bytes32 storemanGroupId) public pure returns (uint256 deposit) { if (storemanGroupId == keccak256("storeman1")) { return 1000 ether; } if (storemanGroupId == keccak256("storeman2")) { return 1000 ether; } if (storemanGroupId == keccak256("storeman3")) { return 1000 ether; } if (storemanGroupId == keccak256("storeman4")) { return 100 ether; } return 0; } function getAncestorInfo(uint256 id) external pure returns ( bytes account, string name, string symbol, uint8 decimals, uint256 chainId ) { if (id == 0) { return ("", "", "WAN", 18, 1); } if (id == 1) { return ("", "", "BTC", 8, 1); } if (id == 2) { return ("", "", "ETH", 18, 1); } if (id == 3) { return ("", "", "ETC", 18, 1); } return ("", "", "", 0, 1); } function getAncestorSymbol(uint id) external pure returns (string symbol, uint8 decimals) { if (id == 0) { return ("WAN", 18); } if (id == 1) { return ("BTC", 8); } if (id == 2) { return ("ETH", 18); } if (id == 3) { return ("ETC", 18); } return ("", 0); } function isDebtClean(bytes32 storemanGroupId) external pure returns (bool) { return false; } }
contracts/crossApproach/CrossDelegateV4.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./CrossStorageV4.sol"; import "./lib/RapidityLibV4.sol"; import "./lib/NFTLibV1.sol"; contract CrossDelegateV4 is CrossStorageV4 { using SafeMath for uint; /** * * EVENTS * **/ /// @notice event of admin config /// @param adminAccount account of admin event SetAdmin(address adminAccount); /// @notice event of setFee or setFees /// @param srcChainID source of cross chain /// @param destChainID destination of cross chain /// @param contractFee contract fee /// @param agentFee agent fee event SetFee(uint indexed srcChainID, uint indexed destChainID, uint contractFee, uint agentFee); /// @notice event of setFee or setFees /// @param tokenPairID ID of token pair /// @param contractFee contract fee event SetTokenPairFee(uint indexed tokenPairID, uint contractFee); /// @notice event of storeman group ID withdraw the original coin to receiver /// @param smgID ID of storeman group /// @param timeStamp timestamp of the withdraw /// @param receiver receiver address /// @param fee shadow coin of the fee which the storeman group pk got it event WithdrawHistoryFeeLogger(bytes32 indexed smgID, uint indexed timeStamp, address indexed receiver, uint fee); /** * * MODIFIERS * */ /// @notice check the admin or not modifier onlyAdmin() { require(msg.sender == admin, "not admin"); _; } /// @notice check the storeman group is ready /// @param smgID ID of storeman group modifier onlyReadySmg(bytes32 smgID) { uint8 status; uint startTime; uint endTime; (status,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupStatus(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); _; } /** * * MANIPULATIONS * */ /// @notice request exchange orignal coin or token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain coin/token /// @param value exchange value /// @param userAccount account of user, used to receive shadow chain token function userLock(bytes32 smgID, uint tokenPairID, uint value, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { address smgFeeProxy = getSmgFeeProxy(); RapidityLibV4.RapidityUserLockParams memory params = RapidityLibV4.RapidityUserLockParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, currentChainID: currentChainID, tokenPairContractFee: mapTokenPairContractFee[tokenPairID], destUserAccount: userAccount, smgFeeProxy: smgFeeProxy }); RapidityLibV4.userLock(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount account of user, used to receive original chain token function userBurn(bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { address smgFeeProxy = getSmgFeeProxy(); RapidityLibV4.RapidityUserBurnParams memory params = RapidityLibV4.RapidityUserBurnParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, currentChainID: currentChainID, tokenPairContractFee: mapTokenPairContractFee[tokenPairID], srcTokenAccount: tokenAccount, destUserAccount: userAccount, smgFeeProxy: smgFeeProxy }); RapidityLibV4.userBurn(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param fee exchange fee /// @param userAccount address of user, used to receive WRC20 token /// @param r signature /// @param s signature function smgMint(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLibV4.RapiditySmgMintParams memory params = RapidityLibV4.RapiditySmgMintParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, destTokenAccount: tokenAccount, destUserAccount: userAccount, smgFeeProxy: (storageData.smgFeeProxy == address(0)) ? owner : storageData.smgFeeProxy // fix: Stack too deep }); RapidityLibV4.smgMint(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, fee, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param fee exchange fee /// @param userAccount address of user, used to receive original token/coin /// @param r signature /// @param s signature function smgRelease(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLibV4.RapiditySmgReleaseParams memory params = RapidityLibV4.RapiditySmgReleaseParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, destTokenAccount: tokenAccount, destUserAccount: userAccount, smgFeeProxy: (storageData.smgFeeProxy == address(0)) ? owner : storageData.smgFeeProxy // fix: Stack too deep }); RapidityLibV4.smgRelease(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, fee, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice set the fee of the storeman group should get /// @param param struct of setFee parameter function setFee(SetFeesParam param) public onlyAdmin { storageData.mapContractFee[param.srcChainID][param.destChainID] = param.contractFee; storageData.mapAgentFee[param.srcChainID][param.destChainID] = param.agentFee; emit SetFee(param.srcChainID, param.destChainID, param.contractFee, param.agentFee); } /// @notice set the fee of the storeman group should get /// @param params struct of setFees parameter function setFees(SetFeesParam [] params) public onlyAdmin { for (uint i = 0; i < params.length; ++i) { storageData.mapContractFee[params[i].srcChainID][params[i].destChainID] = params[i].contractFee; storageData.mapAgentFee[params[i].srcChainID][params[i].destChainID] = params[i].agentFee; emit SetFee(params[i].srcChainID, params[i].destChainID, params[i].contractFee, params[i].agentFee); } } /// @notice set the fee of the storeman group should get /// @param tokenPairID ID of token pair /// @param contractFee contractFee of token pair function setTokenPairFee(uint256 tokenPairID, uint256 contractFee) external onlyAdmin { mapTokenPairContractFee[tokenPairID] = contractFee; emit SetTokenPairFee(tokenPairID, contractFee); } /// @notice set the fee of the storeman group should get /// @param params struct of setTokenPairFees parameter function setTokenPairFees(SetTokenPairFeesParam [] params) public onlyAdmin { for (uint i = 0; i < params.length; ++i) { mapTokenPairContractFee[params[i].tokenPairID] = params[i].contractFee; emit SetTokenPairFee(params[i].tokenPairID, params[i].contractFee); } } function setChainID(uint256 chainID) external onlyAdmin { if (currentChainID == 0) { currentChainID = chainID; } } function setAdmin(address adminAccount) external onlyOwner { admin = adminAccount; emit SetAdmin(adminAccount); } function setUintValue(bytes key, bytes innerKey, uint value) external onlyAdmin { return uintData.setStorage(key, innerKey, value); } function delUintValue(bytes key, bytes innerKey) external onlyAdmin { return uintData.delStorage(key, innerKey); } /// @notice update the initialized state value of this contract /// @param tokenManager address of the token manager /// @param smgAdminProxy address of the storeman group admin /// @param smgFeeProxy address of the proxy to store fee for storeman group /// @param quota address of the quota /// @param sigVerifier address of the signature verifier function setPartners(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) external onlyOwner { // require(tokenManager != address(0) && smgAdminProxy != address(0) && quota != address(0) && sigVerifier != address(0), // "Parameter is invalid"); require(tokenManager != address(0) && smgAdminProxy != address(0) && sigVerifier != address(0), "Parameter is invalid"); storageData.smgAdminProxy = IStoremanGroup(smgAdminProxy); storageData.tokenManager = ITokenManager(tokenManager); // storageData.quota = IQuota(quota); storageData.smgFeeProxy = smgFeeProxy; storageData.sigVerifier = ISignatureVerifier(sigVerifier); } /// @notice withdraw the history fee to foundation account /// @param smgIDs array of storemanGroup ID function smgWithdrawHistoryFee(bytes32 [] smgIDs) external { uint fee; uint currentFee; address smgFeeProxy = storageData.smgFeeProxy; if (smgFeeProxy == address(0)) { smgFeeProxy = owner; } require(smgFeeProxy != address(0), "invalid smgFeeProxy"); for (uint i = 0; i < smgIDs.length; ++i) { currentFee = storageData.mapStoremanFee[smgIDs[i]]; delete storageData.mapStoremanFee[smgIDs[i]]; fee = fee.add(currentFee); emit WithdrawHistoryFeeLogger(smgIDs[i], block.timestamp, smgFeeProxy, currentFee); } if (fee > 0) { smgFeeProxy.transfer(fee); } } /** Get Functions */ function getUintValue(bytes key, bytes innerKey) public view returns (uint) { return uintData.getStorage(key, innerKey); } /// @notice get the fee of the storeman group should get /// @param key key of storeman fee /// @return fee original coin the storeman group should get function getStoremanFee(bytes32 key) external view returns(uint fee) { fee = storageData.mapStoremanFee[key]; } /// @notice get the fee of the storeman group should get /// @param param struct of getFee parameter /// @return fees struct of getFee return function getFee(GetFeesParam param) public view returns(GetFeesReturn fee) { fee.contractFee = storageData.mapContractFee[param.srcChainID][param.destChainID]; fee.agentFee = storageData.mapAgentFee[param.srcChainID][param.destChainID]; } /// @notice get the fee of the storeman group should get /// @param params struct of getFees parameter /// @return fees struct of getFees return function getFees(GetFeesParam [] params) public view returns(GetFeesReturn [] fees) { fees = new GetFeesReturn[](params.length); for (uint i = 0; i < params.length; ++i) { fees[i].contractFee = storageData.mapContractFee[params[i].srcChainID][params[i].destChainID]; fees[i].agentFee = storageData.mapAgentFee[params[i].srcChainID][params[i].destChainID]; } } /// @notice get the token pair fee of the storeman group should get /// @param tokenPairID ID of token pair /// @return contractFee contractFee of token pair function getTokenPairFee(uint256 tokenPairID) external view returns(uint256 contractFee) { contractFee = mapTokenPairContractFee[tokenPairID]; } /// @notice get the token pair fees of the storeman group should get /// @param tokenPairIDs array of tokenPairID /// @return contractFees array of tokenPair contractFee function getTokenPairFees(uint256[] tokenPairIDs) external view returns(uint256 [] contractFees) { contractFees = new uint256[](tokenPairIDs.length); for (uint i = 0; i < tokenPairIDs.length; ++i) { contractFees[i] = mapTokenPairContractFee[tokenPairIDs[i]]; } } /// @notice get the initialized state value of this contract /// @return tokenManager address of the token manager /// @return smgAdminProxy address of the storeman group admin /// @return smgFeeProxy address of the proxy to store fee for storeman group /// @return quota address of the quota /// @return sigVerifier address of the signature verifier function getPartners() external view returns(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) { tokenManager = address(storageData.tokenManager); smgAdminProxy = address(storageData.smgAdminProxy); smgFeeProxy = storageData.smgFeeProxy; quota = address(storageData.quota); sigVerifier = address(storageData.sigVerifier); } /** Private and Internal Functions */ /// @notice check the storeman group is ready or not /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireReadySmgInfo(bytes32 smgID) internal view returns (uint curveID, bytes memory PK) { uint8 status; uint startTime; uint endTime; (,status,,,,curveID,,PK,,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); return (curveID, PK); } /// @notice get the unregistered storeman group info /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireUnregisteredSmgInfo(bytes32 smgID) internal view returns (uint curveID, bytes memory PK) { uint8 status; (,status,,,,curveID,,PK,,,) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.unregistered), "PK is not unregistered"); } /// @notice convert bytes to bytes32 /// @param b bytes array /// @param offset offset of array to begin convert function bytesToBytes32(bytes memory b, uint offset) internal pure returns (bytes32 result) { assembly { result := mload(add(add(b, offset), 32)) } } /// @notice verify signature /// @param curveID ID of elliptic curve /// @param message message to be verified /// @param r Signature info r /// @param s Signature info s function verifySignature(uint curveID, bytes32 message, bytes PK, bytes r, bytes32 s) internal { bytes32 PKx = bytesToBytes32(PK, 0); bytes32 PKy = bytesToBytes32(PK, 32); bytes32 Rx = bytesToBytes32(r, 0); bytes32 Ry = bytesToBytes32(r, 32); require(storageData.sigVerifier.verify(curveID, s, PKx, PKy, Rx, Ry, message), "Signature verification failed"); } function getSmgFeeProxy() internal view returns (address) { address smgFeeProxy = storageData.smgFeeProxy; return (smgFeeProxy == address(0)) ? owner : smgFeeProxy; } //********************************************************************************************* //********************************************************************************************* // NFT /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a `safeTransfer`. This function MUST return the function selector, * otherwise the caller will revert the transaction. The selector to be * returned can be obtained as `this.onERC721Received.selector`. This * function MAY throw to revert and reject the transfer. * Note: the ERC721 contract address is always the message sender. * @param operator The address which called `safeTransferFrom` function * @param from The address which previously owned the token * @param tokenId The NFT identifier which is being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ function onERC721Received(address operator, address from, uint256 tokenId, bytes data) public pure returns(bytes4) { return this.onERC721Received.selector; } function onERC1155Received(address, address, uint256, uint256, bytes memory) public pure returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory) public pure returns (bytes4) { return this.onERC1155BatchReceived.selector; } function userLockNFT(bytes32 smgID, uint tokenPairID, uint[] tokenIDs, uint[] tokenValues, bytes userAccount) public payable notHalted onlyReadySmg(smgID) { require(tokenIDs.length > 0 && tokenIDs.length <= getMaxBatchSize(), "Invalid length"); require(tokenIDs.length == tokenValues.length, "Length mismatch"); NFTLibV1.RapidityUserLockNFTParams memory params = NFTLibV1.RapidityUserLockNFTParams({ smgID: smgID, tokenPairID: tokenPairID, tokenIDs: tokenIDs, tokenValues: tokenValues, currentChainID: currentChainID, tokenPairContractFee: mapTokenPairContractFee[tokenPairID], destUserAccount: userAccount, smgFeeProxy: getSmgFeeProxy() }); NFTLibV1.userLockNFT(storageData, params); } function userBurnNFT(bytes32 smgID, uint tokenPairID, uint[] tokenIDs, uint[] tokenValues, address tokenAccount, bytes userAccount) public payable notHalted onlyReadySmg(smgID) { require(tokenIDs.length > 0 && tokenIDs.length <= getMaxBatchSize(), "Invalid length"); require(tokenIDs.length == tokenValues.length, "Length mismatch"); NFTLibV1.RapidityUserBurnNFTParams memory params = NFTLibV1.RapidityUserBurnNFTParams({ smgID: smgID, tokenPairID: tokenPairID, tokenIDs: tokenIDs, tokenValues: tokenValues, currentChainID: currentChainID, tokenPairContractFee: mapTokenPairContractFee[tokenPairID], srcTokenAccount: tokenAccount, destUserAccount: userAccount, smgFeeProxy: getSmgFeeProxy() }); NFTLibV1.userBurnNFT(storageData, params); } function smgMintNFT(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint[] tokenIDs, uint[] tokenValues, bytes extData, address tokenAccount, address userAccount, bytes r, bytes32 s) public notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); NFTLibV1.RapiditySmgMintNFTParams memory params = NFTLibV1.RapiditySmgMintNFTParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, tokenIDs: tokenIDs, tokenValues: tokenValues, extData: extData, destTokenAccount: tokenAccount, destUserAccount: userAccount }); NFTLibV1.smgMintNFT(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, tokenIDs, tokenValues, extData, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } function smgReleaseNFT(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint[] tokenIDs, uint[] tokenValues, address tokenAccount, address userAccount, bytes r, bytes32 s) public notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); NFTLibV1.RapiditySmgReleaseNFTParams memory params = NFTLibV1.RapiditySmgReleaseNFTParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, tokenIDs: tokenIDs, tokenValues: tokenValues, destTokenAccount: tokenAccount, destUserAccount: userAccount }); NFTLibV1.smgReleaseNFT(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, tokenIDs, tokenValues, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } function setMaxBatchSize(uint _maxBatchSize) external onlyAdmin { maxBatchSize = _maxBatchSize; } function getMaxBatchSize() public view returns (uint) { if(maxBatchSize == 0) { return 20; } return maxBatchSize; } function getBatchFee(uint tokenPairID, uint batchLength) external view returns (uint) { uint contractFee; (, contractFee) = NFTLibV1.getTokenScAddrAndContractFee(storageData, tokenPairID, mapTokenPairContractFee[tokenPairID], currentChainID, batchLength); return contractFee; } }
contracts/components/ReentrancyGuard.sol
pragma solidity 0.4.26; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ contract ReentrancyGuard { bool private _notEntered; constructor () internal { // Storing an initial non-zero value makes deployment a bit more // expensive, but in exchange the refund on every call to nonReentrant // will be lower in amount. Since refunds are capped to a percetange of // the total transaction's gas, it is best to keep them low in cases // like this one, to increase the likelihood of the full refund coming // into effect. _notEntered = true; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { // On the first call to nonReentrant, _notEntered will be true require(_notEntered, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _notEntered = false; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _notEntered = true; } }
contracts/test/TestWanToken.sol
pragma solidity ^0.4.24; import "../tokenManager/WanToken.sol"; import "../components/BasicStorage.sol"; import "./TestIOwned.sol"; contract TestWanToken is BasicStorage { function createToken(string tokenName, string tokenSymbol, uint8 tokenDecimal) external { address tokenInst = new WanToken(tokenName, tokenSymbol, tokenDecimal); addressData.setStorage(bytes(tokenName), bytes(tokenSymbol), tokenInst); uintData.setStorage(bytes(tokenName), bytes(tokenSymbol), tokenDecimal); // TestIOwned(tokenInst).changeOwner(msg.sender); } function changeOwner(string tokenName, string tokenSymbol) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); TestIOwned(tokenInst).changeOwner(msg.sender); } function acceptOwnership(string tokenName, string tokenSymbol) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); TestIOwned(tokenInst).acceptOwnership(); } function getTokenAddr(string tokenName, string tokenSymbol) external view returns (address) { return addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); } function getTokenDecimal(string tokenName, string tokenSymbol) external view returns (uint8) { return uint8(uintData.getStorage(bytes(tokenName), bytes(tokenSymbol))); } function destroyToken(string tokenName, string tokenSymbol) external { addressData.delStorage(bytes(tokenName), bytes(tokenSymbol)); uintData.delStorage(bytes(tokenName), bytes(tokenSymbol)); } }
contracts/storemanGroupAdmin/StoremanGroupDelegate.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; import "../components/Halt.sol"; import "../components/Admin.sol"; import "./StoremanGroupStorage.sol"; import "../interfaces/IListGroup.sol"; import "./StoremanLib.sol"; import "./StoremanType.sol"; import "./IncentiveLib.sol"; import "../interfaces/IQuota.sol"; import "../gpk/lib/GpkTypes.sol"; import "../components/ReentrancyGuard.sol"; contract StoremanGroupDelegate is StoremanGroupStorage, Halt, Admin,ReentrancyGuard { using SafeMath for uint; using Deposit for Deposit.Records; bytes key = "openStoreman"; bytes innerKey = "totalDeposit"; event StoremanGroupRegisterStartEvent(bytes32 indexed groupId, bytes32 indexed preGroupId, uint workStart, uint workDuration, uint registerDuration); event StoremanGroupDismissedEvent(bytes32 indexed groupId, uint dismissTime); event StoremanGroupSetGpkEvent(bytes32 indexed groupId); event updateGroupChainEvent(bytes32 indexed groupId, uint256 indexed chain1, uint256 indexed chain2, uint256 curve1, uint256 curve2); event storemanGroupContributeEvent(address indexed sender, uint indexed value); modifier onlyGroupLeader(bytes32 groupId) { StoremanType.StoremanGroup storage group = data.groups[groupId]; require(msg.sender == group.selectedNode[0], "Sender is not allowed"); _; } /// @notice function for owner set token manager and htlc contract address /// @param metricAddr metricAddr contract address /// @param gpkAddr gpkAddr contract address /// @param quotaAddr quotaAddr contract address function setDependence(address metricAddr, address gpkAddr,address quotaAddr, address posAddr) external onlyOwner { require(metricAddr != address(0), "Invalid metricAddr address"); require(gpkAddr != address(0), "Invalid gpkAddr address"); require(quotaAddr != address(0), "Invalid quotaAddr address"); metric = metricAddr; data.posLib = posAddr; createGpkAddr = gpkAddr; quotaInst = IQuota(quotaAddr); } /// @notice function for owner to open a storeman group. /// @param wkAddrs white list work address array. /// @param senders senders address array of the white list enode. function storemanGroupRegisterStart(StoremanType.StoremanGroupInput smg, address[] wkAddrs, address[] senders) public onlyAdmin { bytes32 groupId = smg.groupId; bytes32 preGroupId = smg.preGroupId; require(wkAddrs.length == senders.length, "Invalid white list length"); require(wkAddrs.length >= data.conf.backupCount, "Insufficient white list"); require(wkAddrs.length <= smg.memberCountDesign+data.conf.backupCount, "Too many whitelist node"); // check preGroupId exist. if(preGroupId != bytes32(0x00)){ StoremanType.StoremanGroup storage preGroup = data.groups[preGroupId]; require(preGroup.status == StoremanType.GroupStatus.ready || preGroup.status == StoremanType.GroupStatus.failed,"invalid preGroup"); } initGroup(groupId, smg); emit StoremanGroupRegisterStartEvent(groupId, preGroupId, smg.workTime, smg.totalTime, smg.registerDuration); emit updateGroupChainEvent(groupId, smg.chain1, smg.chain2, smg.curve1, smg.curve2); return StoremanLib.inheritNode(data, groupId, preGroupId, wkAddrs, senders); } /// @dev set the group chain and curve. function initGroup(bytes32 groupId, StoremanType.StoremanGroupInput smg) private { StoremanType.StoremanGroup storage group = data.groups[groupId]; require(group.status == StoremanType.GroupStatus.none, "group has existed already"); Deposit.Records memory deposit = Deposit.Records(0); Deposit.Records memory depositWeight = Deposit.Records(0); group.deposit = deposit; group.depositWeight = depositWeight; group.registerTime = now; group.status = StoremanType.GroupStatus.curveSeted; group.memberCountDesign = smg.memberCountDesign; group.workTime = smg.workTime; group.totalTime = smg.totalTime; group.registerDuration = smg.registerDuration; group.threshold = smg.threshold; group.minStakeIn = smg.minStakeIn; group.minDelegateIn = smg.minDelegateIn; group.minPartIn = smg.minPartIn; group.delegateFee = smg.delegateFee; group.chain1 = smg.chain1; group.chain2 = smg.chain2; group.curve1 = smg.curve1; group.curve2 = smg.curve2; } function incentiveCandidator( address wkAddr) external { IncentiveLib.incentiveCandidator(data, wkAddr,metric, getGlobalGroupScAddr()); } /// @notice Staker use this interface to stake wan to SC. /// @param groupId the storeman group index. /// @param PK the agent keystore's public key. /// @param enodeID the agent enodeID, use for p2p network. function stakeIn(bytes32 groupId, bytes PK, bytes enodeID) external notHalted payable { return StoremanLib.stakeIn(data, groupId, PK, enodeID); } /// @notice Staker use this interface to append wan to SC. /// @param wkAddr the agent keystore's address, which publickey is specified when stakeIn. function stakeAppend(address wkAddr) external notHalted payable { return StoremanLib.stakeAppend(data, wkAddr); } /// @notice Staker use this interface to anounce he will not continue in next group. /// the next group will open in advance of the current group end. so if a node want to quit, it should call stakeOut before the new group open. /// If the new group has opened, the node in old group can't stake out. /// @param wkAddr the agent keystore's address, which publickey is specified when stakeIn. function stakeOut(address wkAddr) external notHalted { return StoremanLib.stakeOut(data, wkAddr); } function checkCanStakeOut(address wkAddr) external view returns(bool) { return StoremanLib.checkCanStakeOut(data, wkAddr); } function checkCanStakeClaim(address wkAddr) external view returns(bool){ return StoremanLib.checkCanStakeClaim(data, wkAddr); } function checkCanPartnerClaim(address wkAddr, address pnAddr) external view returns(bool) { return StoremanLib.checkCanPartnerClaim(data, wkAddr, pnAddr, getGlobalGroupScAddr()); } function checkCanDelegatorClaim(address wkAddr, address deAddr) external view returns(bool) { return StoremanLib.checkCanDelegatorClaim(data, wkAddr, deAddr, getGlobalGroupScAddr()); } function stakeClaim(address wkAddr) external notHalted nonReentrant { return StoremanLib.stakeClaim(data,wkAddr); } function stakeIncentiveClaim(address wkAddr) external notHalted nonReentrant{ return StoremanLib.stakeIncentiveClaim(data,wkAddr); } function delegateIn(address wkAddr) external notHalted payable { return StoremanLib.delegateIn(data,wkAddr); } function delegateOut(address wkAddr) external { return StoremanLib.delegateOut(data,wkAddr, getGlobalGroupScAddr()); } function delegateClaim(address wkAddr) external notHalted nonReentrant{ return StoremanLib.delegateClaim(data, wkAddr, getGlobalGroupScAddr()); } function delegateIncentiveClaim(address wkAddr) external notHalted nonReentrant{ return StoremanLib.delegateIncentiveClaim(data, wkAddr); } function partIn(address wkAddr) external notHalted payable { return StoremanLib.partIn(data,wkAddr); } function partOut(address wkAddr) external notHalted{ return StoremanLib.partOut(data, wkAddr, getGlobalGroupScAddr()); } function partClaim(address wkAddr) external notHalted nonReentrant{ return StoremanLib.partClaim(data,wkAddr, getGlobalGroupScAddr()); } function getSelectedSmNumber(bytes32 groupId) external view returns(uint) { return StoremanUtil.getSelectedSmNumber(data, groupId); } function getSelectedStoreman(bytes32 groupId) external view returns(address[]) { return StoremanUtil.getSelectedStoreman(data, groupId); } function select(bytes32 groupId) external notHalted { return IncentiveLib.toSelect(data, groupId); } function getSelectedSmInfo(bytes32 groupId, uint index) external view returns(address wkAddr, bytes PK, bytes enodeId) { StoremanType.StoremanGroup storage group = data.groups[groupId]; address addr = group.selectedNode[index]; StoremanType.Candidate storage sk = data.candidates[0][addr]; return (sk.wkAddr, sk.PK, sk.enodeID); } // To change group status for unexpected reason. function updateGroupStatus(bytes32 groupId, StoremanType.GroupStatus status) external onlyAdmin { StoremanType.StoremanGroup storage group = data.groups[groupId]; group.status = status; } function getStoremanIncentive(address wkAddr, uint day) external view returns(uint incentive) { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; return sk.incentive[day]; } function getSmDelegatorInfoIncentive(address wkAddr, address deAddr, uint day) external view returns ( uint) { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage de = sk.delegators[deAddr]; return (de.incentive[day]); } function getSmDelegatorInfo(address wkAddr, address deAddr) external view returns (address sender, uint deposit, uint incentive, bool quited) { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage de = sk.delegators[deAddr]; return (deAddr, de.deposit.getLastValue(), de.incentive[0], de.quited); } function getSmPartnerInfo(address wkAddr, address pnAddr) external view returns (address sender, uint deposit, bool quited) { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; StoremanType.Delegator storage pn = sk.partners[pnAddr]; return (pnAddr, pn.deposit.getLastValue(), pn.quited); } function getSmPartnerAddr(address wkAddr, uint index) external view returns(address pkAddr) { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; return sk.partMap[index]; } function getSmDelegatorAddr(address wkAddr, uint index) external view returns(address deAddr) { StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; return sk.delegatorMap[index]; } function setGpk(bytes32 groupId, bytes gpk1, bytes gpk2) external { require(msg.sender == createGpkAddr, "Sender is not allowed"); StoremanType.StoremanGroup storage group = data.groups[groupId]; require(group.status == StoremanType.GroupStatus.selected,"invalid status"); group.gpk1 = gpk1; group.gpk2 = gpk2; group.status = StoremanType.GroupStatus.ready; addActiveGroup(groupId, group.workTime, group.workTime+group.totalTime); emit StoremanGroupSetGpkEvent(groupId); } function addActiveGroupId(bytes32 groupId) external onlyAdmin{ address addr = getGlobalGroupScAddr(); StoremanType.StoremanGroup storage group = data.groups[groupId]; IListGroup(addr).addActiveGroup(groupId, group.workTime, group.workTime+group.totalTime); } function getDependence() public view returns(address metricAddr, address gpkAddr,address quotaAddr, address posAddr, address listGroupAddr) { return (metric, createGpkAddr,address(quotaInst), data.posLib, getGlobalGroupScAddr()); } function setGlobalGroupScAddr(address _addr) external onlyOwner { addressData.setStorage(key, innerKey, _addr); } function getGlobalGroupScAddr() public view returns(address) { return addressData.getStorage(key, innerKey); } function addActiveGroup(bytes32 groupId, uint startTime, uint endTime) private { address addr = getGlobalGroupScAddr(); IListGroup(addr).addActiveGroup(groupId, startTime, endTime); } function cleanExpiredGroup() private { address addr = getGlobalGroupScAddr(); IListGroup(addr).cleanExpiredGroup(); } function getActiveGroupIds(uint epochId) external view returns(bytes32[]){ address addr = getGlobalGroupScAddr(); return IListGroup(addr).getActiveGroupIds(epochId); } function setInvalidSm(bytes32 groupId, uint[] indexs, GpkTypes.SlashType[] slashTypes) external returns(bool isContinue) { require(msg.sender == createGpkAddr, "Sender is not allowed"); StoremanType.StoremanGroup storage group = data.groups[groupId]; if (group.status != StoremanType.GroupStatus.selected) { return false; } for (uint i = 0; i < indexs.length; i++) { StoremanType.Candidate storage skt = data.candidates[0][group.selectedNode[indexs[i]]]; if (slashTypes[i] == GpkTypes.SlashType.SijInvalid || slashTypes[i] == GpkTypes.SlashType.CheckInvalid || slashTypes[i] == GpkTypes.SlashType.SijTimeout) { recordSmSlash(group.selectedNode[indexs[i]]); } IncentiveLib.cleanSmNode(skt, groupId); if (group.tickedCount + group.whiteCount >= group.whiteCountAll) { group.status = StoremanType.GroupStatus.failed; return false; } group.tickedNode[group.tickedCount] = group.selectedNode[indexs[i]]; group.selectedNode[indexs[i]] = group.whiteMap[group.whiteCount + group.tickedCount]; group.tickedCount++; StoremanType.Candidate storage skn = data.candidates[0][group.selectedNode[indexs[i]]]; if(skn.groupId == 0) { skn.groupId = groupId; }else { skn.nextGroupId = groupId; } } IncentiveLib.setGroupDeposit(data, group); return true; } function recordSmSlash(address wk) public { require((msg.sender == metric) || (msg.sender == createGpkAddr), "Sender is not allowed"); StoremanType.Candidate storage sk = data.candidates[0][wk]; sk.slashedCount++; } function getThresholdByGrpId(bytes32 groupId) external view returns (uint){ StoremanType.StoremanGroup storage group = data.groups[groupId]; return group.threshold; } /// @notice function for storeman group apply unregistration through the delegate /// @param groupId storeman group groupId function storemanGroupUnregister(bytes32 groupId) external notHalted onlyGroupLeader(groupId) { StoremanLib.storemanGroupUnregister(data, groupId); return cleanExpiredGroup(); } /// @notice function for storeman group apply unregistration through the delegate /// @param groupId storeman groupId function storemanGroupDismiss(bytes32 groupId) external notHalted onlyGroupLeader(groupId) { StoremanType.StoremanGroup storage group = data.groups[groupId]; bool quitable = quotaInst.isDebtClean(groupId); require(quitable, "can not dismiss"); group.status = StoremanType.GroupStatus.dismissed; emit StoremanGroupDismissedEvent(groupId, now); StoremanType.Candidate storage sk; for(uint i=0; i<group.selectedCount; i++){ sk = data.candidates[0][group.selectedNode[i]]; IncentiveLib.rotateSkGroup(data.posLib, sk, group); } } function checkGroupDismissable(bytes32 groupId) external view returns(bool) { bool dismissable = quotaInst.isDebtClean(groupId); return dismissable; } function getStoremanInfo(address wkAddr) external view returns(StoremanType.StoremanInfo si){ StoremanType.Candidate storage sk = data.candidates[0][wkAddr]; si.sender = sk.sender; si.enodeID = sk.enodeID; si.PK = sk.PK; si.wkAddr = sk.wkAddr; si.isWhite = sk.isWhite; si.quited = sk.quited; si.delegatorCount = sk.delegatorCount; si.delegateDeposit = sk.delegateDeposit; si.partnerCount = sk.partnerCount; si.partnerDeposit = sk.partnerDeposit; si.crossIncoming = sk.crossIncoming; si.slashedCount = sk.slashedCount; si.incentivedDelegator = sk.incentivedDelegator; si.incentivedDay = sk.incentivedDay; si.groupId = sk.groupId; si.incentive = sk.incentive[0]; si.nextGroupId = sk.nextGroupId; si.deposit = sk.deposit.getLastValue(); } function getStoremanGroupInfo(bytes32 id) external view returns(StoremanType.StoremanGroupInfo info){ StoremanType.StoremanGroup storage smg = data.groups[id]; info.groupId = id; info.status = smg.status; info.deposit = smg.deposit.getLastValue(); info.depositWeight = smg.depositWeight.getLastValue(); info.selectedCount = smg.selectedCount; info.memberCount = smg.memberCount; info.whiteCount = smg.whiteCount; info.whiteCountAll = smg.whiteCountAll; info.startTime = smg.workTime; info.endTime = smg.workTime+smg.totalTime; info.registerTime = smg.registerTime; info.registerDuration = smg.registerDuration; info.memberCountDesign = smg.memberCountDesign; info.threshold = smg.threshold; info.chain1 = smg.chain1; info.chain2 = smg.chain2; info.curve1 = smg.curve1; info.curve2 = smg.curve2; info.tickedCount = smg.tickedCount; info.minStakeIn = smg.minStakeIn; info.minDelegateIn = smg.minDelegateIn; info.minPartIn = smg.minPartIn; info.crossIncoming = smg.crossIncoming; info.gpk1 = smg.gpk1; info.gpk2 = smg.gpk2; info.delegateFee = smg.delegateFee; } function getStoremanGroupConfig(bytes32 id) external view returns(bytes32 groupId, StoremanType.GroupStatus status, uint deposit, uint chain1, uint chain2, uint curve1, uint curve2, bytes gpk1, bytes gpk2, uint startTime, uint endTime) { StoremanType.StoremanGroup storage smg = data.groups[id]; return (id, smg.status,smg.deposit.getLastValue(), smg.chain1, smg.chain2,smg.curve1, smg.curve2, smg.gpk1, smg.gpk2, smg.workTime, smg.workTime+smg.totalTime); } function getStoremanGroupStatus(bytes32 id) public view returns(StoremanType.GroupStatus status, uint startTime, uint endTime) { StoremanType.StoremanGroup storage smg = data.groups[id]; return (smg.status, smg.workTime, smg.workTime+smg.totalTime); } function getDeposit(bytes32 id) external view returns (uint) { return data.groups[id].deposit.getLastValue(); } // function getStoremanGroupTime(bytes32 id) // external // view // returns(bytes32 groupId, uint registerTime, uint registerDuration, uint startTime, uint endTime) // { // StoremanType.StoremanGroup storage smg = data.groups[id]; // return (smg.groupId, smg.registerTime, smg.registerDuration, smg.workTime, smg.workTime+smg.totalTime); // } function checkGroupIncentive(bytes32 id, uint day) external view returns ( uint) { StoremanType.StoremanGroup storage group = data.groups[id]; return group.groupIncentive[day]; } function contribute() external payable { emit storemanGroupContributeEvent(msg.sender, msg.value); data.contribution = data.contribution.add(msg.value); return; } function smgTransfer(bytes32 smgID) external payable{ StoremanType.StoremanGroup storage group = data.groups[smgID]; group.crossIncoming = group.crossIncoming.add(msg.value); uint i; StoremanType.Candidate storage sk; for(i=0; i<group.selectedCount; i++) { sk = data.candidates[0][group.selectedNode[i]]; sk.crossIncoming = sk.crossIncoming.add(msg.value.div(group.selectedCount)); } } function setChainTypeCo(uint chain1, uint chain2, uint co) external onlyAdmin { if(chain1 < chain2) { data.chainTypeCo[chain1][chain2] = co; } else { data.chainTypeCo[chain2][chain1] = co; } } function getChainTypeCo(uint chain1, uint chain2) external view returns (uint co) { return IncentiveLib.getChainTypeCo(data, chain1, chain2); } function getStoremanConf() external view returns(uint backupCount, uint standaloneWeight, uint delegationMulti) { return (data.conf.backupCount, data.conf.standaloneWeight, data.conf.DelegationMulti); } function updateStoremanConf(uint backupCount, uint standaloneWeight, uint DelegationMulti) external onlyAdmin { data.conf.backupCount = backupCount; data.conf.standaloneWeight = standaloneWeight; data.conf.DelegationMulti = DelegationMulti; } function getGlobalIncentive() external view returns(uint contribution, uint totalReward) { return (data.contribution, data.totalReward); } }
contracts/crossApproach/CrossDelegate.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "../components/Halt.sol"; import "../components/ReentrancyGuard.sol"; import "./CrossStorage.sol"; import "./lib/HTLCDebtLib.sol"; import "./lib/RapidityLib.sol"; contract CrossDelegate is CrossStorage, ReentrancyGuard, Halt { using SafeMath for uint; bytes constant currentChainIDKey = "current"; bytes constant currentChainIDInnerKey = "chainID"; /** * * EVENTS * **/ /// @notice event of storeman group ID withdraw the original coin to receiver /// @param smgID ID of storemanGroup /// @param timeStamp timestamp of the withdraw /// @param receiver receiver address /// @param fee shadow coin of the fee which the storeman group pk got it event SmgWithdrawFeeLogger(bytes32 indexed smgID, uint timeStamp, address indexed receiver, uint fee); /** * * MODIFIERS * */ /// @notice check the storeman group is ready /// @param smgID ID of storeman group modifier onlyReadySmg(bytes32 smgID) { uint8 status; uint startTime; uint endTime; (status,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupStatus(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); _; } /** * * MANIPULATIONS * */ /// @notice check the storeman group is ready or not /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireReadySmgInfo(bytes32 smgID) private view returns (uint curveID, bytes memory PK) { uint8 status; uint startTime; uint endTime; (,status,,,,curveID,,PK,,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); return (curveID, PK); } /// @notice get the unregistered storeman group info /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireUnregisteredSmgInfo(bytes32 smgID) private view returns (uint curveID, bytes memory PK) { uint8 status; (,status,,,,curveID,,PK,,,) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.unregistered), "PK is not unregistered"); } /// @notice request exchange orignal coin or token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain coin/token /// @param value exchange value /// @param userAccount account of user, used to receive shadow chain token function userLock(bytes32 smgID, uint tokenPairID, uint value, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { RapidityLib.RapidityUserLockParams memory params = RapidityLib.RapidityUserLockParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, userShadowAccount: userAccount }); RapidityLib.userLock(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount account of user, used to receive original chain token function userBurn(bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { RapidityLib.RapidityUserBurnParams memory params = RapidityLib.RapidityUserBurnParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, shadowTokenAccount: tokenAccount, userOrigAccount: userAccount }); RapidityLib.userBurn(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount address of user, used to receive WRC20 token /// @param r signature /// @param s signature function smgMint(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLib.RapiditySmgMintParams memory params = RapidityLib.RapiditySmgMintParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, shadowTokenAccount: tokenAccount, userShadowAccount: userAccount }); RapidityLib.smgMint(storageData, params); uint currentChainID = getUintValue(currentChainIDKey, currentChainIDInnerKey); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount address of user, used to receive original token/coin /// @param r signature /// @param s signature function smgRelease(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLib.RapiditySmgReleaseParams memory params = RapidityLib.RapiditySmgReleaseParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, origTokenAccount: tokenAccount, userOrigAccount: userAccount }); RapidityLib.smgRelease(storageData, params); uint currentChainID = getUintValue(currentChainIDKey, currentChainIDInnerKey); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice transfer storeman asset /// @param uniqueID random number (likes old xHash) /// @param srcSmgID ID of src storeman /// @param destSmgID ID of dst storeman /// @param r signature /// @param s signature function transferAsset(bytes32 uniqueID, bytes32 srcSmgID, bytes32 destSmgID, bytes r, bytes32 s) external notHalted onlyReadySmg(destSmgID) { uint curveID; bytes memory PK; (curveID, PK) = acquireUnregisteredSmgInfo(srcSmgID); HTLCDebtLib.DebtAssetParams memory params = HTLCDebtLib.DebtAssetParams({ uniqueID: uniqueID, srcSmgID: srcSmgID, destSmgID: destSmgID }); HTLCDebtLib.transferAsset(storageData, params); bytes32 mHash = sha256(abi.encode(getUintValue(currentChainIDKey, currentChainIDInnerKey), uniqueID, destSmgID)); verifySignature(curveID, mHash, PK, r, s); } /// @notice receive storeman debt /// @param uniqueID random number (likes old xHash) /// @param srcSmgID ID of src storeman /// @param destSmgID ID of dst storeman /// @param r signature /// @param s signature function receiveDebt(bytes32 uniqueID, bytes32 srcSmgID, bytes32 destSmgID, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(destSmgID); HTLCDebtLib.DebtAssetParams memory params = HTLCDebtLib.DebtAssetParams({ uniqueID: uniqueID, srcSmgID: srcSmgID, destSmgID: destSmgID }); HTLCDebtLib.receiveDebt(storageData, params); uint currentChainID = getUintValue(currentChainIDKey, currentChainIDInnerKey); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, srcSmgID)); verifySignature(curveID, mHash, PK, r, s); } /// @notice get the fee of the storeman group should get /// @param smgID ID of storemanGroup /// @return fee original coin the storeman group should get function getStoremanFee(bytes32 smgID) external view returns(uint fee) { fee = storageData.mapStoremanFee[smgID]; } /// @notice get the fee of the storeman group should get /// @param origChainID ID of token original chain /// @param shadowChainID ID of token shadow chain /// @param lockFee Coin the storeman group should get while storeman redeem user lock /// @param revokeFee Coin the storeman group should get while user revoke its lock function setFees(uint origChainID, uint shadowChainID, uint lockFee, uint revokeFee) external onlyOwner { storageData.mapLockFee[origChainID][shadowChainID] = lockFee; storageData.mapRevokeFee[origChainID][shadowChainID] = revokeFee; } /// @notice get the fee of the storeman group should get /// @param origChainID Original chain ID /// @param shadowChainID Shadow Chain ID /// @return lockFee Coin the storeman group should get while storeman redeem user lock /// @return revokeFee Coin the storeman group should get while user revoke its lock function getFees(uint origChainID, uint shadowChainID) external view returns(uint lockFee, uint revokeFee) { lockFee = storageData.mapLockFee[origChainID][shadowChainID]; revokeFee = storageData.mapRevokeFee[origChainID][shadowChainID]; } /// @notice get the fee of the storeman group should get /// @param time Coin the storeman group should get while storeman redeem user lock function setLockedTime(uint time) external onlyOwner { lockedTime = time; } /// @notice get the fee of the storeman group should get /// @param xHash hash of HTLC random number /// @return leftLockTime left time of locked transaction function getLeftLockedTime(bytes32 xHash) external view returns (uint leftLockedTime) { leftLockedTime = storageData.htlcTxData.getLeftLockedTime(xHash); } /// @notice update the initialized state value of this contract /// @param tokenManager address of the token manager /// @param smgAdminProxy address of the storeman group admin /// @param smgFeeProxy address of the proxy to store fee for storeman group /// @param quota address of the quota /// @param sigVerifier address of the signature verifier function setPartners(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) external onlyOwner { // require(tokenManager != address(0) && smgAdminProxy != address(0) && quota != address(0) && sigVerifier != address(0), // "Parameter is invalid"); require(tokenManager != address(0) && smgAdminProxy != address(0) && sigVerifier != address(0), "Parameter is invalid"); storageData.smgAdminProxy = IStoremanGroup(smgAdminProxy); storageData.tokenManager = ITokenManager(tokenManager); storageData.quota = IQuota(quota); storageData.smgFeeProxy = smgFeeProxy; storageData.sigVerifier = ISignatureVerifier(sigVerifier); } /// @notice get the initialized state value of this contract /// @return tokenManager address of the token manager /// @return smgAdminProxy address of the storeman group admin /// @return smgFeeProxy address of the proxy to store fee for storeman group /// @return quota address of the quota /// @return sigVerifier address of the signature verifier function getPartners() external view returns(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) { tokenManager = address(storageData.tokenManager); smgAdminProxy = address(storageData.smgAdminProxy); smgFeeProxy = storageData.smgFeeProxy; quota = address(storageData.quota); sigVerifier = address(storageData.sigVerifier); } /// @notice get the fee of the storeman group should get /// @param timeout Timeout for storeman group receiver withdraw fee, uint second function setWithdrawFeeTimeout(uint timeout) external onlyOwner { smgFeeReceiverTimeout = timeout; } /// @notice storeman group withdraw the fee to receiver account /// @param smgID ID of the storeman group /// @param receiver account of the receiver /// @param r signature /// @param s signature function smgWithdrawFee(bytes32 smgID, uint timeStamp, address receiver, bytes r, bytes32 s) external nonReentrant { require(now < timeStamp.add(smgFeeReceiverTimeout), "The receiver address expired"); uint fee = storageData.mapStoremanFee[smgID]; require(fee > 0, "Fee is null"); delete storageData.mapStoremanFee[smgID]; receiver.transfer(fee); uint curveID; bytes memory PK; (,,,,,curveID,,PK,,,) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); uint currentChainID = getUintValue(currentChainIDKey, currentChainIDInnerKey); verifySignature(curveID, sha256(abi.encode(currentChainID, timeStamp, receiver)), PK, r, s); emit SmgWithdrawFeeLogger(smgID, now, receiver, fee); } /// @notice convert bytes to bytes32 /// @param b bytes array /// @param offset offset of array to begin convert function bytesToBytes32(bytes memory b, uint offset) private pure returns (bytes32 result) { assembly { result := mload(add(add(b, offset), 32)) } } /// @notice verify signature /// @param curveID ID of elliptic curve /// @param message message to be verified /// @param r Signature info r /// @param s Signature info s function verifySignature(uint curveID, bytes32 message, bytes PK, bytes r, bytes32 s) private // view { bytes32 PKx = bytesToBytes32(PK, 0); bytes32 PKy = bytesToBytes32(PK, 32); bytes32 Rx = bytesToBytes32(r, 0); bytes32 Ry = bytesToBytes32(r, 32); require(storageData.sigVerifier.verify(curveID, s, PKx, PKy, Rx, Ry, message), "Signature verification failed"); } /* uintData */ function setUintValue(bytes key, bytes innerKey, uint value) external onlyOwner { return uintData.setStorage(key, innerKey, value); } function getUintValue(bytes key, bytes innerKey) public view returns (uint) { return uintData.getStorage(key, innerKey); } function delUintValue(bytes key, bytes innerKey) external onlyOwner { return uintData.delStorage(key, innerKey); } }
contracts/tokenManager/TokenManagerProxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; /** * Math operations with safety checks */ import "../components/Admin.sol"; import "./TokenManagerStorage.sol"; import "../components/Proxy.sol"; contract TokenManagerProxy is TokenManagerStorage, Admin, Proxy { /** * * MANIPULATIONS * */ /// @notice function for setting or upgrading TokenManagerDelegate address by owner /// @param impl TokenManagerDelegate contract address function upgradeTo(address impl) public onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require(impl != _implementation, "Cannot upgrade to the same implementation"); _implementation = impl; emit Upgraded(impl); } }
openzeppelin-eth/contracts/token/ERC721/ERC721Enumerable.sol
pragma solidity ^0.4.24; import "../../zos-lib/Initializable.sol"; import "./IERC721Enumerable.sol"; import "./ERC721.sol"; import "../../introspection/ERC165.sol"; contract ERC721Enumerable is Initializable, ERC165, ERC721, IERC721Enumerable { // Mapping from owner to list of owned token IDs mapping(address => uint256[]) private _ownedTokens; // Mapping from token ID to index of the owner tokens list mapping(uint256 => uint256) private _ownedTokensIndex; // Array with all token ids, used for enumeration uint256[] private _allTokens; // Mapping from token id to position in the allTokens array mapping(uint256 => uint256) private _allTokensIndex; bytes4 private constant _InterfaceId_ERC721Enumerable = 0x780e9d63; /** * 0x780e9d63 === * bytes4(keccak256('totalSupply()')) ^ * bytes4(keccak256('tokenOfOwnerByIndex(address,uint256)')) ^ * bytes4(keccak256('tokenByIndex(uint256)')) */ /** * @dev Constructor function */ function initialize() public initializer { require(ERC721._hasBeenInitialized()); // register the supported interface to conform to ERC721 via ERC165 _registerInterface(_InterfaceId_ERC721Enumerable); } function _hasBeenInitialized() internal view returns (bool) { return supportsInterface(_InterfaceId_ERC721Enumerable); } /** * @dev Gets the token ID at a given index of the tokens list of the requested owner * @param owner address owning the tokens list to be accessed * @param index uint256 representing the index to be accessed of the requested tokens list * @return uint256 token ID at the given index of the tokens list owned by the requested address */ function tokenOfOwnerByIndex( address owner, uint256 index ) public view returns (uint256) { require(index < balanceOf(owner)); return _ownedTokens[owner][index]; } /** * @dev Gets the total amount of tokens stored by the contract * @return uint256 representing the total amount of tokens */ function totalSupply() public view returns (uint256) { return _allTokens.length; } /** * @dev Gets the token ID at a given index of all the tokens in this contract * Reverts if the index is greater or equal to the total number of tokens * @param index uint256 representing the index to be accessed of the tokens list * @return uint256 token ID at the given index of the tokens list */ function tokenByIndex(uint256 index) public view returns (uint256) { require(index < totalSupply()); return _allTokens[index]; } /** * @dev Internal function to add a token ID to the list of a given address * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenTo(address to, uint256 tokenId) internal { super._addTokenTo(to, tokenId); uint256 length = _ownedTokens[to].length; _ownedTokens[to].push(tokenId); _ownedTokensIndex[tokenId] = length; } /** * @dev Internal function to remove a token ID from the list of a given address * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFrom(address from, uint256 tokenId) internal { super._removeTokenFrom(from, tokenId); // To prevent a gap in the array, we store the last token in the index of the token to delete, and // then delete the last slot. uint256 tokenIndex = _ownedTokensIndex[tokenId]; uint256 lastTokenIndex = _ownedTokens[from].length.sub(1); uint256 lastToken = _ownedTokens[from][lastTokenIndex]; _ownedTokens[from][tokenIndex] = lastToken; // This also deletes the contents at the last position of the array _ownedTokens[from].length--; // Note that this will handle single-element arrays. In that case, both tokenIndex and lastTokenIndex are going to // be zero. Then we can make sure that we will remove tokenId from the ownedTokens list since we are first swapping // the lastToken to the first position, and then dropping the element placed in the last position of the list _ownedTokensIndex[tokenId] = 0; _ownedTokensIndex[lastToken] = tokenIndex; } /** * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to address the beneficiary that will own the minted token * @param tokenId uint256 ID of the token to be minted by the msg.sender */ function _mint(address to, uint256 tokenId) internal { super._mint(to, tokenId); _allTokensIndex[tokenId] = _allTokens.length; _allTokens.push(tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * @param owner owner of the token to burn * @param tokenId uint256 ID of the token being burned by the msg.sender */ function _burn(address owner, uint256 tokenId) internal { super._burn(owner, tokenId); // Reorg all tokens array uint256 tokenIndex = _allTokensIndex[tokenId]; uint256 lastTokenIndex = _allTokens.length.sub(1); uint256 lastToken = _allTokens[lastTokenIndex]; _allTokens[tokenIndex] = lastToken; _allTokens[lastTokenIndex] = 0; _allTokens.length--; _allTokensIndex[tokenId] = 0; _allTokensIndex[lastToken] = tokenIndex; } uint256[50] private ______gap; }
contracts/storemanGroupAdmin/StoremanGroupProxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // Code style according to: https://github.com/wanchain/wanchain-token/blob/master/style-guide.rst pragma solidity ^0.4.24; import "../components/Halt.sol"; import "../components/Admin.sol"; import "./StoremanGroupStorage.sol"; import "../components/Proxy.sol"; import "../components/ReentrancyGuard.sol"; contract StoremanGroupProxy is StoremanGroupStorage, Halt, Admin, ReentrancyGuard,Proxy { /** * * MANIPULATIONS * */ /// @notice function for setting or upgrading StoremanGroupDelegate address by owner /// @param impl StoremanGroupDelegate contract address function upgradeTo(address impl) public onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require(impl != _implementation, "Cannot upgrade to the same implementation"); _implementation = impl; emit Upgraded(impl); } }
openzeppelin-eth/contracts/token/ERC721/IERC721Receiver.sol
pragma solidity ^0.4.24; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ contract IERC721Receiver { /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a `safeTransfer`. This function MUST return the function selector, * otherwise the caller will revert the transaction. The selector to be * returned can be obtained as `this.onERC721Received.selector`. This * function MAY throw to revert and reject the transfer. * Note: the ERC721 contract address is always the message sender. * @param operator The address which called `safeTransferFrom` function * @param from The address which previously owned the token * @param tokenId The NFT identifier which is being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ function onERC721Received( address operator, address from, uint256 tokenId, bytes data ) public returns(bytes4); }
contracts/interfaces/ISmgFeeProxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; interface ISmgFeeProxy { function smgTransfer(bytes32 smgID) external payable; }
contracts/interfaces/IConfig.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; interface IConfig { function getCurve(uint8 curveId) external returns(address); }
contracts/config/ConfigStorage.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; import "../components/BasicStorage.sol"; contract ConfigStorage is BasicStorage { /************************************************************ ** ** VARIABLES ** ************************************************************/ /// curve -> contract address mapping(uint8 => address) curves; }
contracts/test/TestNftTokenCreator.sol
pragma solidity ^0.4.24; import "../interfaces/IMappingToken.sol"; import "../components/BasicStorage.sol"; import "./MappingNftToken.sol"; import "./TestIOwned.sol"; contract TestNftTokenCreator is BasicStorage { address _admin; modifier onlyAdmin { require(_admin != address(0), "admin is null"); _; } function setAdmin(address admin) external { _admin = admin; } function getAdmin() external view returns (address) { return _admin; } function createToken(string tokenName, string tokenSymbol, uint8 tokenDecimal) external { address tokenInst = new MappingNftToken(tokenName, tokenSymbol); addressData.setStorage(bytes(tokenName), bytes(tokenSymbol), tokenInst); uintData.setStorage(bytes(tokenName), bytes(tokenSymbol), tokenDecimal); // TestIOwned(tokenInst).changeOwner(msg.sender); } function changeOwner(string tokenName, string tokenSymbol) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); TestIOwned(tokenInst).changeOwner(msg.sender); } function acceptOwnership(string tokenName, string tokenSymbol) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); TestIOwned(tokenInst).acceptOwnership(); } function getTokenAddr(string tokenName, string tokenSymbol) external view returns (address) { return addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); } function mintToken(string tokenName, string tokenSymbol, address to, uint value) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); IMappingToken(tokenInst).mint(to, value); } function burnToken(string tokenName, string tokenSymbol, address from, uint value) external { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); IMappingToken(tokenInst).burn(from, value); } function tokenBalance(string tokenName, string tokenSymbol, address owner) external view returns (uint balance) { address tokenInst = addressData.getStorage(bytes(tokenName), bytes(tokenSymbol)); balance = MappingNftToken(tokenInst).balanceOf(owner); } function getTokenDecimal(string tokenName, string tokenSymbol) external view returns (uint8) { return uint8(uintData.getStorage(bytes(tokenName), bytes(tokenSymbol))); } function destroyToken(string tokenName, string tokenSymbol) external { addressData.delStorage(bytes(tokenName), bytes(tokenSymbol)); uintData.delStorage(bytes(tokenName), bytes(tokenSymbol)); } }
contracts/test/FakePosLib.sol
pragma solidity ^0.4.26; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; library FakePosLib { using SafeMath for uint; uint public constant DIVISOR = 10000; address constant PRECOMPILE_CONTRACT_ADDR = 0x268; function getEpochId(uint256 blockTime) public pure returns (uint256) { return blockTime/1; } function getMinIncentive (uint256 smgDeposit,uint256 targetSecond, uint256 totalDeposit) public pure returns(uint256) { uint posCap = 60000000000; if(totalDeposit < posCap) return 30000000; uint cap = posCap.mul(smgDeposit).div(totalDeposit); return cap > 30000000 ? 30000000 : cap; } }
openzeppelin-eth/contracts/token/ERC721/ERC721Full.sol
pragma solidity ^0.4.24; import "../../zos-lib/Initializable.sol"; import "./ERC721.sol"; import "./ERC721Enumerable.sol"; import "./ERC721Metadata.sol"; /** * @title Full ERC721 Token * This implementation includes all the required and some optional functionality of the ERC721 standard * Moreover, it includes approve all functionality using operator terminology * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721Full is Initializable, ERC721, ERC721Enumerable, ERC721Metadata { uint256[50] private ______gap; }
contracts/crossApproach/CrossProxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; /** * Math operations with safety checks */ import "../components/Proxy.sol"; import "../components/Halt.sol"; import "../components/ReentrancyGuard.sol"; import "./CrossStorage.sol"; contract CrossProxy is CrossStorage, ReentrancyGuard, Halt, Proxy { ///@dev update the address of CrossDelegate contract ///@param impl the address of the new CrossDelegate contract function upgradeTo(address impl) public onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require(impl != _implementation, "Cannot upgrade to the same implementation"); _implementation = impl; emit Upgraded(impl); } }
contracts/crossApproach/CrossDelegateV3.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./CrossStorageV3.sol"; import "./lib/RapidityLibV3.sol"; contract CrossDelegateV3 is CrossStorageV3 { using SafeMath for uint; /** * * EVENTS * **/ /// @notice event of admin config /// @param adminAccount account of admin event SetAdmin(address adminAccount); /// @notice event of setFee or setFees /// @param srcChainID source of cross chain /// @param destChainID destination of cross chain /// @param contractFee contract fee /// @param agentFee agent fee event SetFee(uint indexed srcChainID, uint indexed destChainID, uint contractFee, uint agentFee); /// @notice event of setFee or setFees /// @param tokenPairID ID of token pair /// @param contractFee contract fee event SetTokenPairFee(uint indexed tokenPairID, uint contractFee); /// @notice event of storeman group ID withdraw the original coin to receiver /// @param smgID ID of storeman group /// @param timeStamp timestamp of the withdraw /// @param receiver receiver address /// @param fee shadow coin of the fee which the storeman group pk got it event WithdrawHistoryFeeLogger(bytes32 indexed smgID, uint indexed timeStamp, address indexed receiver, uint fee); /** * * MODIFIERS * */ /// @notice check the admin or not modifier onlyAdmin() { require(msg.sender == admin, "not admin"); _; } /// @notice check the storeman group is ready /// @param smgID ID of storeman group modifier onlyReadySmg(bytes32 smgID) { uint8 status; uint startTime; uint endTime; (status,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupStatus(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); _; } /** * * MANIPULATIONS * */ /// @notice request exchange orignal coin or token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain coin/token /// @param value exchange value /// @param userAccount account of user, used to receive shadow chain token function userLock(bytes32 smgID, uint tokenPairID, uint value, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { address smgFeeProxy = getSmgFeeProxy(); RapidityLibV3.RapidityUserLockParams memory params = RapidityLibV3.RapidityUserLockParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, currentChainID: currentChainID, tokenPairContractFee: mapTokenPairContractFee[tokenPairID], destUserAccount: userAccount, smgFeeProxy: smgFeeProxy }); RapidityLibV3.userLock(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount account of user, used to receive original chain token function userBurn(bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { address smgFeeProxy = getSmgFeeProxy(); RapidityLibV3.RapidityUserBurnParams memory params = RapidityLibV3.RapidityUserBurnParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, currentChainID: currentChainID, tokenPairContractFee: mapTokenPairContractFee[tokenPairID], srcTokenAccount: tokenAccount, destUserAccount: userAccount, smgFeeProxy: smgFeeProxy }); RapidityLibV3.userBurn(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param fee exchange fee /// @param userAccount address of user, used to receive WRC20 token /// @param r signature /// @param s signature function smgMint(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLibV3.RapiditySmgMintParams memory params = RapidityLibV3.RapiditySmgMintParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, destTokenAccount: tokenAccount, destUserAccount: userAccount, smgFeeProxy: (storageData.smgFeeProxy == address(0)) ? owner : storageData.smgFeeProxy // fix: Stack too deep }); RapidityLibV3.smgMint(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, fee, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param fee exchange fee /// @param userAccount address of user, used to receive original token/coin /// @param r signature /// @param s signature function smgRelease(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLibV3.RapiditySmgReleaseParams memory params = RapidityLibV3.RapiditySmgReleaseParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, destTokenAccount: tokenAccount, destUserAccount: userAccount, smgFeeProxy: (storageData.smgFeeProxy == address(0)) ? owner : storageData.smgFeeProxy // fix: Stack too deep }); RapidityLibV3.smgRelease(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, fee, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice set the fee of the storeman group should get /// @param param struct of setFee parameter function setFee(SetFeesParam param) public onlyAdmin { storageData.mapContractFee[param.srcChainID][param.destChainID] = param.contractFee; storageData.mapAgentFee[param.srcChainID][param.destChainID] = param.agentFee; emit SetFee(param.srcChainID, param.destChainID, param.contractFee, param.agentFee); } /// @notice set the fee of the storeman group should get /// @param params struct of setFees parameter function setFees(SetFeesParam [] params) public onlyAdmin { for (uint i = 0; i < params.length; ++i) { storageData.mapContractFee[params[i].srcChainID][params[i].destChainID] = params[i].contractFee; storageData.mapAgentFee[params[i].srcChainID][params[i].destChainID] = params[i].agentFee; emit SetFee(params[i].srcChainID, params[i].destChainID, params[i].contractFee, params[i].agentFee); } } /// @notice set the fee of the storeman group should get /// @param tokenPairID ID of token pair /// @param contractFee contractFee of token pair function setTokenPairFee(uint256 tokenPairID, uint256 contractFee) external onlyAdmin { mapTokenPairContractFee[tokenPairID] = contractFee; emit SetTokenPairFee(tokenPairID, contractFee); } /// @notice set the fee of the storeman group should get /// @param params struct of setTokenPairFees parameter function setTokenPairFees(SetTokenPairFeesParam [] params) public onlyAdmin { for (uint i = 0; i < params.length; ++i) { mapTokenPairContractFee[params[i].tokenPairID] = params[i].contractFee; emit SetTokenPairFee(params[i].tokenPairID, params[i].contractFee); } } function setChainID(uint256 chainID) external onlyAdmin { if (currentChainID == 0) { currentChainID = chainID; } } function setAdmin(address adminAccount) external onlyOwner { admin = adminAccount; emit SetAdmin(adminAccount); } function setUintValue(bytes key, bytes innerKey, uint value) external onlyAdmin { return uintData.setStorage(key, innerKey, value); } function delUintValue(bytes key, bytes innerKey) external onlyAdmin { return uintData.delStorage(key, innerKey); } /// @notice update the initialized state value of this contract /// @param tokenManager address of the token manager /// @param smgAdminProxy address of the storeman group admin /// @param smgFeeProxy address of the proxy to store fee for storeman group /// @param quota address of the quota /// @param sigVerifier address of the signature verifier function setPartners(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) external onlyOwner { // require(tokenManager != address(0) && smgAdminProxy != address(0) && quota != address(0) && sigVerifier != address(0), // "Parameter is invalid"); require(tokenManager != address(0) && smgAdminProxy != address(0) && sigVerifier != address(0), "Parameter is invalid"); storageData.smgAdminProxy = IStoremanGroup(smgAdminProxy); storageData.tokenManager = ITokenManager(tokenManager); // storageData.quota = IQuota(quota); storageData.smgFeeProxy = smgFeeProxy; storageData.sigVerifier = ISignatureVerifier(sigVerifier); } /// @notice withdraw the history fee to foundation account /// @param smgIDs array of storemanGroup ID function smgWithdrawHistoryFee(bytes32 [] smgIDs) external { uint fee; uint currentFee; address smgFeeProxy = storageData.smgFeeProxy; if (smgFeeProxy == address(0)) { smgFeeProxy = owner; } require(smgFeeProxy != address(0), "invalid smgFeeProxy"); for (uint i = 0; i < smgIDs.length; ++i) { currentFee = storageData.mapStoremanFee[smgIDs[i]]; delete storageData.mapStoremanFee[smgIDs[i]]; fee = fee.add(currentFee); emit WithdrawHistoryFeeLogger(smgIDs[i], block.timestamp, smgFeeProxy, currentFee); } if (fee > 0) { smgFeeProxy.transfer(fee); } } /** Get Functions */ function getUintValue(bytes key, bytes innerKey) public view returns (uint) { return uintData.getStorage(key, innerKey); } /// @notice get the fee of the storeman group should get /// @param key key of storeman fee /// @return fee original coin the storeman group should get function getStoremanFee(bytes32 key) external view returns(uint fee) { fee = storageData.mapStoremanFee[key]; } /// @notice get the fee of the storeman group should get /// @param param struct of getFee parameter /// @return fees struct of getFee return function getFee(GetFeesParam param) public view returns(GetFeesReturn fee) { fee.contractFee = storageData.mapContractFee[param.srcChainID][param.destChainID]; fee.agentFee = storageData.mapAgentFee[param.srcChainID][param.destChainID]; } /// @notice get the fee of the storeman group should get /// @param params struct of getFees parameter /// @return fees struct of getFees return function getFees(GetFeesParam [] params) public view returns(GetFeesReturn [] fees) { fees = new GetFeesReturn[](params.length); for (uint i = 0; i < params.length; ++i) { fees[i].contractFee = storageData.mapContractFee[params[i].srcChainID][params[i].destChainID]; fees[i].agentFee = storageData.mapAgentFee[params[i].srcChainID][params[i].destChainID]; } } /// @notice get the token pair fee of the storeman group should get /// @param tokenPairID ID of token pair /// @return contractFee contractFee of token pair function getTokenPairFee(uint256 tokenPairID) external view returns(uint256 contractFee) { contractFee = mapTokenPairContractFee[tokenPairID]; } /// @notice get the token pair fees of the storeman group should get /// @param tokenPairIDs array of tokenPairID /// @return contractFees array of tokenPair contractFee function getTokenPairFees(uint256[] tokenPairIDs) external view returns(uint256 [] contractFees) { contractFees = new uint256[](tokenPairIDs.length); for (uint i = 0; i < tokenPairIDs.length; ++i) { contractFees[i] = mapTokenPairContractFee[tokenPairIDs[i]]; } } /// @notice get the initialized state value of this contract /// @return tokenManager address of the token manager /// @return smgAdminProxy address of the storeman group admin /// @return smgFeeProxy address of the proxy to store fee for storeman group /// @return quota address of the quota /// @return sigVerifier address of the signature verifier function getPartners() external view returns(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) { tokenManager = address(storageData.tokenManager); smgAdminProxy = address(storageData.smgAdminProxy); smgFeeProxy = storageData.smgFeeProxy; quota = address(storageData.quota); sigVerifier = address(storageData.sigVerifier); } /** Private and Internal Functions */ /// @notice check the storeman group is ready or not /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireReadySmgInfo(bytes32 smgID) internal view returns (uint curveID, bytes memory PK) { uint8 status; uint startTime; uint endTime; (,status,,,,curveID,,PK,,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); return (curveID, PK); } /// @notice get the unregistered storeman group info /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireUnregisteredSmgInfo(bytes32 smgID) internal view returns (uint curveID, bytes memory PK) { uint8 status; (,status,,,,curveID,,PK,,,) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.unregistered), "PK is not unregistered"); } /// @notice convert bytes to bytes32 /// @param b bytes array /// @param offset offset of array to begin convert function bytesToBytes32(bytes memory b, uint offset) internal pure returns (bytes32 result) { assembly { result := mload(add(add(b, offset), 32)) } } /// @notice verify signature /// @param curveID ID of elliptic curve /// @param message message to be verified /// @param r Signature info r /// @param s Signature info s function verifySignature(uint curveID, bytes32 message, bytes PK, bytes r, bytes32 s) internal { bytes32 PKx = bytesToBytes32(PK, 0); bytes32 PKy = bytesToBytes32(PK, 32); bytes32 Rx = bytesToBytes32(r, 0); bytes32 Ry = bytesToBytes32(r, 32); require(storageData.sigVerifier.verify(curveID, s, PKx, PKy, Rx, Ry, message), "Signature verification failed"); } function getSmgFeeProxy() internal view returns (address) { address smgFeeProxy = storageData.smgFeeProxy; return (smgFeeProxy == address(0)) ? owner : smgFeeProxy; } /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a `safeTransfer`. This function MUST return the function selector, * otherwise the caller will revert the transaction. The selector to be * returned can be obtained as `this.onERC721Received.selector`. This * function MAY throw to revert and reject the transfer. * Note: the ERC721 contract address is always the message sender. * @param operator The address which called `safeTransferFrom` function * @param from The address which previously owned the token * @param tokenId The NFT identifier which is being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ function onERC721Received(address operator, address from, uint256 tokenId, bytes data) public pure returns(bytes4) { return this.onERC721Received.selector; } }
contracts/components/Proxy.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; /** * Math operations with safety checks */ contract Proxy { event Upgraded(address indexed implementation); address internal _implementation; function implementation() public view returns (address) { return _implementation; } function () external payable { address _impl = _implementation; require(_impl != address(0), "implementation contract not set"); assembly { let ptr := mload(0x40) calldatacopy(ptr, 0, calldatasize) let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0) let size := returndatasize returndatacopy(ptr, 0, size) switch result case 0 { revert(ptr, size) } default { return(ptr, size) } } } }
contracts/crossApproach/CrossDelegateV2.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import "./CrossStorageV2.sol"; import "./lib/HTLCDebtLibV2.sol"; import "./lib/RapidityLibV2.sol"; contract CrossDelegateV2 is CrossStorageV2 { using SafeMath for uint; /** * * EVENTS * **/ /// @notice event of admin config /// @param adminAccount account of admin event SetAdmin(address adminAccount); /// @notice event of setFee or setFees /// @param srcChainID source of cross chain /// @param destChainID destination of cross chain /// @param contractFee contract fee /// @param agentFee agent fee event SetFee(uint srcChainID, uint destChainID, uint contractFee, uint agentFee); /// @notice event of storeman group ID withdraw the original coin to receiver /// @param smgID ID of storemanGroup /// @param timeStamp timestamp of the withdraw /// @param receiver receiver address /// @param fee shadow coin of the fee which the storeman group pk got it event SmgWithdrawFeeLogger(bytes32 indexed smgID, uint indexed timeStamp, address indexed receiver, uint fee); event WithdrawContractFeeLogger(uint indexed block, uint indexed timeStamp, address indexed receiver, uint fee); /** * * MODIFIERS * */ /// @notice check the admin or not modifier onlyAdmin() { require(msg.sender == admin, "not admin"); _; } /// @notice check the storeman group is ready /// @param smgID ID of storeman group modifier onlyReadySmg(bytes32 smgID) { uint8 status; uint startTime; uint endTime; (status,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupStatus(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); _; } /** * * MANIPULATIONS * */ /// @notice request exchange orignal coin or token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain coin/token /// @param value exchange value /// @param userAccount account of user, used to receive shadow chain token function userLock(bytes32 smgID, uint tokenPairID, uint value, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { RapidityLibV2.RapidityUserLockParams memory params = RapidityLibV2.RapidityUserLockParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, currentChainID: currentChainID, destUserAccount: userAccount }); RapidityLibV2.userLock(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount account of user, used to receive original chain token function userBurn(bytes32 smgID, uint tokenPairID, uint value, uint fee, address tokenAccount, bytes userAccount) external payable notHalted onlyReadySmg(smgID) { RapidityLibV2.RapidityUserBurnParams memory params = RapidityLibV2.RapidityUserBurnParams({ smgID: smgID, tokenPairID: tokenPairID, value: value, fee: fee, currentChainID: currentChainID, srcTokenAccount: tokenAccount, destUserAccount: userAccount }); RapidityLibV2.userBurn(storageData, params); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount address of user, used to receive WRC20 token /// @param r signature /// @param s signature function smgMint(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLibV2.RapiditySmgMintParams memory params = RapidityLibV2.RapiditySmgMintParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, destTokenAccount: tokenAccount, destUserAccount: userAccount }); RapidityLibV2.smgMint(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice request exchange RC20 token with WRC20 on wanchain /// @param uniqueID fast cross chain random number /// @param smgID ID of storeman /// @param tokenPairID token pair ID of cross chain token /// @param value exchange value /// @param userAccount address of user, used to receive original token/coin /// @param r signature /// @param s signature function smgRelease(bytes32 uniqueID, bytes32 smgID, uint tokenPairID, uint value, address tokenAccount, address userAccount, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(smgID); RapidityLibV2.RapiditySmgReleaseParams memory params = RapidityLibV2.RapiditySmgReleaseParams({ uniqueID: uniqueID, smgID: smgID, tokenPairID: tokenPairID, value: value, destTokenAccount: tokenAccount, destUserAccount: userAccount }); RapidityLibV2.smgRelease(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, tokenPairID, value, tokenAccount, userAccount)); verifySignature(curveID, mHash, PK, r, s); } /// @notice transfer storeman asset /// @param uniqueID random number (likes old xHash) /// @param srcSmgID ID of src storeman /// @param destSmgID ID of dst storeman /// @param r signature /// @param s signature function transferAsset(bytes32 uniqueID, bytes32 srcSmgID, bytes32 destSmgID, bytes r, bytes32 s) external notHalted onlyReadySmg(destSmgID) { uint curveID; bytes memory PK; (curveID, PK) = acquireUnregisteredSmgInfo(srcSmgID); HTLCDebtLibV2.DebtAssetParams memory params = HTLCDebtLibV2.DebtAssetParams({ uniqueID: uniqueID, srcSmgID: srcSmgID, destSmgID: destSmgID }); HTLCDebtLibV2.transferAsset(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, destSmgID)); verifySignature(curveID, mHash, PK, r, s); } /// @notice receive storeman debt /// @param uniqueID random number (likes old xHash) /// @param srcSmgID ID of src storeman /// @param destSmgID ID of dst storeman /// @param r signature /// @param s signature function receiveDebt(bytes32 uniqueID, bytes32 srcSmgID, bytes32 destSmgID, bytes r, bytes32 s) external notHalted { uint curveID; bytes memory PK; (curveID, PK) = acquireReadySmgInfo(destSmgID); HTLCDebtLibV2.DebtAssetParams memory params = HTLCDebtLibV2.DebtAssetParams({ uniqueID: uniqueID, srcSmgID: srcSmgID, destSmgID: destSmgID }); HTLCDebtLibV2.receiveDebt(storageData, params); bytes32 mHash = sha256(abi.encode(currentChainID, uniqueID, srcSmgID)); verifySignature(curveID, mHash, PK, r, s); } /// @notice get the fee of the storeman group should get /// @param param struct of setFee parameter function setFee(SetFeesParam param) public onlyAdmin { storageData.mapContractFee[param.srcChainID][param.destChainID] = param.contractFee; storageData.mapAgentFee[param.srcChainID][param.destChainID] = param.agentFee; emit SetFee(param.srcChainID, param.destChainID, param.contractFee, param.agentFee); } /// @notice get the fee of the storeman group should get /// @param params struct of setFees parameter function setFees(SetFeesParam [] params) public onlyAdmin { for (uint i = 0; i < params.length; ++i) { storageData.mapContractFee[params[i].srcChainID][params[i].destChainID] = params[i].contractFee; storageData.mapAgentFee[params[i].srcChainID][params[i].destChainID] = params[i].agentFee; emit SetFee(params[i].srcChainID, params[i].destChainID, params[i].contractFee, params[i].agentFee); } } function setChainID(uint256 chainID) external onlyAdmin { if (currentChainID == 0) { currentChainID = chainID; } } function setAdmin(address adminAccount) external onlyOwner { admin = adminAccount; emit SetAdmin(adminAccount); } function setUintValue(bytes key, bytes innerKey, uint value) external onlyAdmin { return uintData.setStorage(key, innerKey, value); } function delUintValue(bytes key, bytes innerKey) external onlyAdmin { return uintData.delStorage(key, innerKey); } /// @notice update the initialized state value of this contract /// @param tokenManager address of the token manager /// @param smgAdminProxy address of the storeman group admin /// @param smgFeeProxy address of the proxy to store fee for storeman group /// @param quota address of the quota /// @param sigVerifier address of the signature verifier function setPartners(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) external onlyOwner { // require(tokenManager != address(0) && smgAdminProxy != address(0) && quota != address(0) && sigVerifier != address(0), // "Parameter is invalid"); require(tokenManager != address(0) && smgAdminProxy != address(0) && sigVerifier != address(0), "Parameter is invalid"); storageData.smgAdminProxy = IStoremanGroup(smgAdminProxy); storageData.tokenManager = ITokenManager(tokenManager); storageData.quota = IQuota(quota); storageData.smgFeeProxy = smgFeeProxy; storageData.sigVerifier = ISignatureVerifier(sigVerifier); } /// @notice withdraw the history fee to foundation account /// @param smgIDs array of storemanGroup ID function smgWithdrawFee(bytes32 [] smgIDs) external { uint fee; uint currentFee; address smgFeeProxy = storageData.smgFeeProxy; if (smgFeeProxy == address(0)) { smgFeeProxy = owner; } require(smgFeeProxy != address(0), "invalid smgFeeProxy"); for (uint i = 0; i < smgIDs.length; ++i) { currentFee = storageData.mapStoremanFee[smgIDs[i]]; delete storageData.mapStoremanFee[smgIDs[i]]; fee = fee.add(currentFee); emit SmgWithdrawFeeLogger(smgIDs[i], block.timestamp, smgFeeProxy, currentFee); } currentFee = storageData.mapStoremanFee[bytes32(0)]; if (currentFee > 0) { delete storageData.mapStoremanFee[bytes32(0)]; fee = fee.add(currentFee); } require(fee > 0, "Fee is null"); smgFeeProxy.transfer(fee); emit WithdrawContractFeeLogger(block.number, block.timestamp, smgFeeProxy, fee); } /** Get Functions */ function getUintValue(bytes key, bytes innerKey) public view returns (uint) { return uintData.getStorage(key, innerKey); } /// @notice get the fee of the storeman group should get /// @param smgID ID of storemanGroup /// @return fee original coin the storeman group should get function getStoremanFee(bytes32 smgID) external view returns(uint fee) { fee = storageData.mapStoremanFee[smgID]; } /// @notice get the fee of the storeman group should get /// @param param struct of getFee parameter /// @return fees struct of getFee return function getFee(GetFeesParam param) public view returns(GetFeesReturn fee) { fee.contractFee = storageData.mapContractFee[param.srcChainID][param.destChainID]; fee.agentFee = storageData.mapAgentFee[param.srcChainID][param.destChainID]; } /// @notice get the fee of the storeman group should get /// @param params struct of getFees parameter /// @return fees struct of getFees return function getFees(GetFeesParam [] params) public view returns(GetFeesReturn [] fees) { fees = new GetFeesReturn[](params.length); for (uint i = 0; i < params.length; ++i) { fees[i].contractFee = storageData.mapContractFee[params[i].srcChainID][params[i].destChainID]; fees[i].agentFee = storageData.mapAgentFee[params[i].srcChainID][params[i].destChainID]; } } /// @notice get the initialized state value of this contract /// @return tokenManager address of the token manager /// @return smgAdminProxy address of the storeman group admin /// @return smgFeeProxy address of the proxy to store fee for storeman group /// @return quota address of the quota /// @return sigVerifier address of the signature verifier function getPartners() external view returns(address tokenManager, address smgAdminProxy, address smgFeeProxy, address quota, address sigVerifier) { tokenManager = address(storageData.tokenManager); smgAdminProxy = address(storageData.smgAdminProxy); smgFeeProxy = storageData.smgFeeProxy; quota = address(storageData.quota); sigVerifier = address(storageData.sigVerifier); } /** Private and Internal Functions */ /// @notice check the storeman group is ready or not /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireReadySmgInfo(bytes32 smgID) internal view returns (uint curveID, bytes memory PK) { uint8 status; uint startTime; uint endTime; (,status,,,,curveID,,PK,,startTime,endTime) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.ready) && now >= startTime && now <= endTime, "PK is not ready"); return (curveID, PK); } /// @notice get the unregistered storeman group info /// @param smgID ID of storeman group /// @return curveID ID of elliptic curve /// @return PK PK of storeman group function acquireUnregisteredSmgInfo(bytes32 smgID) internal view returns (uint curveID, bytes memory PK) { uint8 status; (,status,,,,curveID,,PK,,,) = storageData.smgAdminProxy.getStoremanGroupConfig(smgID); require(status == uint8(GroupStatus.unregistered), "PK is not unregistered"); } /// @notice convert bytes to bytes32 /// @param b bytes array /// @param offset offset of array to begin convert function bytesToBytes32(bytes memory b, uint offset) internal pure returns (bytes32 result) { assembly { result := mload(add(add(b, offset), 32)) } } /// @notice verify signature /// @param curveID ID of elliptic curve /// @param message message to be verified /// @param r Signature info r /// @param s Signature info s function verifySignature(uint curveID, bytes32 message, bytes PK, bytes r, bytes32 s) internal { bytes32 PKx = bytesToBytes32(PK, 0); bytes32 PKy = bytesToBytes32(PK, 32); bytes32 Rx = bytesToBytes32(r, 0); bytes32 Ry = bytesToBytes32(r, 32); require(storageData.sigVerifier.verify(curveID, s, PKx, PKy, Rx, Ry, message), "Signature verification failed"); } }
contracts/test/TestBasicStorage.sol
pragma solidity ^0.4.24; import "../components/BasicStorage.sol"; contract TestBasicStorage is BasicStorage { /* uintData */ function setUintData(bytes key, bytes innerKey, uint value) external { return uintData.setStorage(key, innerKey, value); } function getUintData(bytes key, bytes innerKey) external view returns (uint) { return uintData.getStorage(key, innerKey); } function delUintData(bytes key, bytes innerKey) external { return uintData.delStorage(key, innerKey); } /* boolData */ function setBoolData(bytes key, bytes innerKey, bool value) external { boolData.setStorage(key, innerKey, value); } function getBoolData(bytes key, bytes innerKey) external view returns (bool) { return boolData.getStorage(key, innerKey); } function delBoolData(bytes key, bytes innerKey) external { return boolData.delStorage(key, innerKey); } /* addressData */ function setAddressData(bytes key, bytes innerKey, address value) external { addressData.setStorage(key, innerKey, value); } function getAddressData(bytes key, bytes innerKey) external view returns (address) { return addressData.getStorage(key, innerKey); } function delAddressData(bytes key, bytes innerKey) external { return addressData.delStorage(key, innerKey); } /* bytesData */ function setBytesData(bytes key, bytes innerKey, bytes value) external { bytesData.setStorage(key, innerKey, value); } function getBytesData(bytes key, bytes innerKey) external view returns (bytes) { return bytesData.getStorage(key, innerKey); } function delBytesData(bytes key, bytes innerKey) external { return bytesData.delStorage(key, innerKey); } /* stringData */ function setStringData(bytes key, bytes innerKey, string value) external { stringData.setStorage(key, innerKey, value); } function getStringData(bytes key, bytes innerKey) external view returns (string) { return stringData.getStorage(key, innerKey); } function delStringData(bytes key, bytes innerKey) external { return stringData.delStorage(key, innerKey); } }
contracts/crossApproach/lib/CrossTypes.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; import "../../interfaces/IRC20Protocol.sol"; import "../../interfaces/IQuota.sol"; import "../../interfaces/IStoremanGroup.sol"; import "../../interfaces/ITokenManager.sol"; import "../../interfaces/ISignatureVerifier.sol"; import "./HTLCTxLib.sol"; import "./RapidityTxLib.sol"; library CrossTypes { using SafeMath for uint; /** * * STRUCTURES * */ struct Data { /// map of the htlc transaction info HTLCTxLib.Data htlcTxData; /// map of the rapidity transaction info RapidityTxLib.Data rapidityTxData; /// quota data of storeman group IQuota quota; /// token manager instance interface ITokenManager tokenManager; /// storemanGroup admin instance interface IStoremanGroup smgAdminProxy; /// storemanGroup fee admin instance address address smgFeeProxy; ISignatureVerifier sigVerifier; /// @notice transaction fee, smgID => fee mapping(bytes32 => uint) mapStoremanFee; /// @notice transaction fee, origChainID => shadowChainID => fee mapping(uint => mapping(uint =>uint)) mapLockFee; /// @notice transaction fee, origChainID => shadowChainID => fee mapping(uint => mapping(uint =>uint)) mapRevokeFee; } /** * * MANIPULATIONS * */ // /// @notice convert bytes32 to address // /// @param b bytes32 // function bytes32ToAddress(bytes32 b) internal pure returns (address) { // return address(uint160(bytes20(b))); // high // // return address(uint160(uint256(b))); // low // } /// @notice convert bytes to address /// @param b bytes function bytesToAddress(bytes b) internal pure returns (address addr) { assembly { addr := mload(add(b,20)) } } function transfer(address tokenScAddr, address to, uint value) internal returns(bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenScAddr).balanceOf(to); // IRC20Protocol(tokenScAddr).transfer(to, value); tokenScAddr.call(bytes4(keccak256("transfer(address,uint256)")), to, value); afterBalance = IRC20Protocol(tokenScAddr).balanceOf(to); return afterBalance == beforeBalance.add(value); } function transferFrom(address tokenScAddr, address from, address to, uint value) internal returns(bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenScAddr).balanceOf(to); // IRC20Protocol(tokenScAddr).transferFrom(from, to, value); tokenScAddr.call(bytes4(keccak256("transferFrom(address,address,uint256)")), from, to, value); afterBalance = IRC20Protocol(tokenScAddr).balanceOf(to); return afterBalance == beforeBalance.add(value); } }
contracts/config/ConfigProxy.sol
/* Copyright 2020 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; pragma experimental ABIEncoderV2; /** * Math operations with safety checks */ import "../components/Halt.sol"; import "../components/Admin.sol"; import "./ConfigStorage.sol"; import "../components/Proxy.sol"; contract ConfigProxy is ConfigStorage, Halt, Admin, Proxy { ///@dev update the address of ConfigDelegate contract ///@param impl the address of the new ConfigDelegate contract function upgradeTo(address impl) public onlyOwner { require(impl != address(0), "Cannot upgrade to invalid address"); require(impl != _implementation, "Cannot upgrade to the same implementation"); _implementation = impl; emit Upgraded(impl); } }
contracts/storemanGroupAdmin/StoremanType.sol
pragma solidity ^0.4.26; import "./Deposit.sol"; library StoremanType { using Deposit for Deposit.Records; enum GroupStatus {none, initial,curveSeted, failed,selected,ready,unregistered, dismissed} //ready: gpk finished. struct Delegator { bool quited; uint index; // for delete from candidate; Deposit.Records deposit; mapping(uint=>uint) incentive; } struct Candidate { address sender; bytes enodeID; bytes PK; address wkAddr; bool isWhite; bool quited; uint delegatorCount; uint delegateDeposit; // only used when selecting. need not records. uint partnerCount; uint partnerDeposit; uint crossIncoming; uint slashedCount; uint incentivedDelegator; // how may delegator have beend incentived, == delegatorCount means incentive finished. uint incentivedDay; bytes32 groupId; bytes32 nextGroupId; Deposit.Records deposit; // the sk hiself's deposit. mapping(uint=>uint) incentive; // without delegation.. set to 0 after claim. // delegator index => delegator addr mapping(uint=>address) delegatorMap; mapping(address=>Delegator) delegators; // partner index => partner address mapping(uint=>address) partMap; mapping(address=>Delegator) partners; } struct StoremanGroup { GroupStatus status; Deposit.Records deposit; //group's deposit, used for calculate group incentive Deposit.Records depositWeight; // use for incentive distribution in a group uint selectedCount; uint memberCount; uint whiteCount; // only used node, don't include backup. uint whiteCountAll; // all uint workTime; uint totalTime; uint registerTime; uint registerDuration; // how long allow to staking. check when stakeIn tx. uint memberCountDesign; uint threshold; uint chain1; uint chain2; uint curve1; uint curve2; uint tickedCount; uint minStakeIn; uint minDelegateIn; uint minPartIn; uint crossIncoming; bytes gpk1; bytes gpk2; uint delegateFee; // div(10000) mapping(uint=>uint) tickedType; mapping(uint=>address) tickedNode; mapping(uint=>address) skMap; mapping(uint=>address) selectedNode; mapping(uint=>address) whiteMap; mapping(address=>address) whiteWk; // the white list specified when start group. the from sender of whitelist. mapping(uint=>uint) groupIncentive; // by day. } struct StoremanGlobalConf { uint standaloneWeight; // defult 15000; need mul 10000 uint DelegationMulti; // 10 uint backupCount; // 3 uint chainTypeCoDefault; //10000 uint maxSlashedCount; } struct StoremanData { uint contribution; uint totalReward; address posLib; StoremanGlobalConf conf; mapping(bytes32 => StoremanType.StoremanGroup) groups; mapping(uint=>mapping(address=>StoremanType.Candidate)) candidates; mapping(uint=> mapping(uint => uint)) chainTypeCo; } struct StoremanInfo { address sender; bytes enodeID; bytes PK; address wkAddr; bool isWhite; bool quited; uint delegatorCount; uint delegateDeposit; uint partnerCount; uint partnerDeposit; uint crossIncoming; uint slashedCount; uint incentivedDelegator; uint incentivedDay; bytes32 groupId; bytes32 nextGroupId; uint deposit; uint incentive; } struct StoremanGroupInfo { bytes32 groupId; GroupStatus status; uint deposit; uint depositWeight; uint selectedCount; uint memberCount; uint whiteCount; // only used node, don't include backup. uint whiteCountAll; // all uint startTime; uint endTime; uint registerTime; uint registerDuration; // how long allow to staking. check when stakeIn tx. uint memberCountDesign; uint threshold; uint chain1; uint chain2; uint curve1; uint curve2; uint tickedCount; uint minStakeIn; uint minDelegateIn; uint minPartIn; uint crossIncoming; bytes gpk1; bytes gpk2; uint delegateFee; } struct StoremanGroupInput { bytes32 groupId; bytes32 preGroupId; uint workTime; // cross chain start time uint totalTime; // cross chain duration. uint registerDuration; uint memberCountDesign; uint threshold; uint chain1; uint chain2; uint curve1; uint curve2; uint minStakeIn; uint minDelegateIn; uint minPartIn; uint delegateFee; } }
contracts/test/TestIOwned.sol
pragma solidity ^0.4.24; interface TestIOwned { function changeOwner(address _newOwner) external; function acceptOwnership() external; }
contracts/interfaces/IOracle.sol
pragma solidity 0.4.26; interface IOracle { function getDeposit(bytes32 smgID) external view returns (uint); function getValue(bytes32 key) external view returns (uint); function getValues(bytes32[] keys) external view returns (uint[] values); function getStoremanGroupConfig( bytes32 id ) external view returns(bytes32 groupId, uint8 status, uint deposit, uint chain1, uint chain2, uint curve1, uint curve2, bytes gpk1, bytes gpk2, uint startTime, uint endTime); }
contracts/interfaces/IERC1155.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; //interface IERC1155 is IERC165 { interface IERC1155 { ///** // * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`. // */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); ///** // * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all // * transfers. // */ //event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); /** * @dev Returns the amount of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ //function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `amount`. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * Emits a {TransferBatch} event. * * Requirements: * * - `ids` and `amounts` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data) external; }
contracts/schnorr/Bn128.sol
pragma solidity ^0.4.24; import 'openzeppelin-eth/contracts/math/SafeMath.sol'; contract Bn128 { using SafeMath for uint; uint256 constant gx = 0x1; uint256 constant gy = 0x2; /// @dev Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1. uint256 constant order = 21888242871839275222246405745257275088548364400416034343698204186575808495617; function getGx() public pure returns (uint256) { return gx; } function getGy() public pure returns (uint256) { return gy; } function getOrder() public pure returns (uint256) { return order; } function ecadd( uint256 x1, uint256 y1, uint256 x2, uint256 y2 ) public view returns (uint256 x3, uint256 y3) { uint256[2] memory outValue; uint256[4] memory input; input[0] = x1; input[1] = y1; input[2] = x2; input[3] = y2; assembly { if iszero(staticcall(gas, 0x06, input, 0x80, outValue, 0x40)) { revert(0, 0) } } x3 = outValue[0]; y3 = outValue[1]; } function ecmul( uint256 x1, uint256 y1, uint256 scalar ) public view returns (uint256 x2, uint256 y2) { uint256[2] memory outValue; uint256[3] memory input; input[0] = x1; input[1] = y1; input[2] = scalar; assembly { if iszero(staticcall(gas, 0x07, input, 0x60, outValue, 0x40)) { revert(0, 0) } } x2 = outValue[0]; y2 = outValue[1]; } }
contracts/tokenManager/MappingToken.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity 0.4.26; import '../components/StandardToken.sol'; import '../components/Owned.sol'; contract MappingToken is StandardToken, Owned { using SafeMath for uint; /**************************************************************************** ** ** MODIFIERS ** ****************************************************************************/ modifier onlyMeaningfulValue(uint value) { require(value > 0, "Value is null"); _; } /**************************************************************************** ** ** EVENTS ** ****************************************************************************/ ///@notice Initialize the TokenManager address ///@dev Initialize the TokenManager address ///@param tokenName The token name to be used ///@param tokenSymbol The token symbol to be used ///@param tokenDecimal The token decimals to be used constructor(string tokenName, string tokenSymbol, uint8 tokenDecimal) public { name = tokenName; symbol = tokenSymbol; decimals = tokenDecimal; } /**************************************************************************** ** ** MANIPULATIONS ** ****************************************************************************/ /// @notice Create token /// @dev Create token /// @param account Address will receive token /// @param value Amount of token to be minted function mint(address account, uint value) external onlyOwner onlyMeaningfulValue(value) { balances[account] = balances[account].add(value); totalSupply = totalSupply.add(value); emit Transfer(address(0), account, value); } /// @notice Burn token /// @dev Burn token /// @param account Address of whose token will be burnt /// @param value Amount of token to be burnt function burn(address account, uint value) external onlyOwner onlyMeaningfulValue(value) { balances[account] = balances[account].sub(value); totalSupply = totalSupply.sub(value); emit Transfer(account, address(0), value); } /// @notice update token name, symbol /// @dev update token name, symbol /// @param _name token new name /// @param _symbol token new symbol function update(string _name, string _symbol) external onlyOwner { name = _name; symbol = _symbol; } }
openzeppelin-eth/contracts/math/SafeMath.sol
pragma solidity ^0.4.24; /** * @title SafeMath * @dev Math operations with safety checks that revert on error */ library SafeMath { /** * @dev Multiplies two numbers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b); return c; } /** * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0); // Solidity only automatically asserts when dividing by 0 uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Divides two numbers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } }
contracts/crossApproach/lib/RapidityLibV3.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; pragma experimental ABIEncoderV2; import 'openzeppelin-eth/contracts/token/ERC721/IERC721.sol'; import "./RapidityTxLib.sol"; import "./CrossTypesV1.sol"; import "../../interfaces/ITokenManager.sol"; import "../../interfaces/IRC20Protocol.sol"; library RapidityLibV3 { using SafeMath for uint; using RapidityTxLib for RapidityTxLib.Data; enum TokenCrossType {ERC20, ERC721} /** * * STRUCTURES * */ /// @notice struct of Rapidity storeman mint lock parameters struct RapidityUserLockParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint currentChainID; /// current chain ID uint tokenPairContractFee; /// fee of token pair bytes destUserAccount; /// account of shadow chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity storeman mint lock parameters struct RapiditySmgMintParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint fee; /// exchange token fee address destTokenAccount; /// shadow token account address destUserAccount; /// account of shadow chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity user burn lock parameters struct RapidityUserBurnParams { bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint currentChainID; /// current chain ID uint fee; /// exchange token fee uint tokenPairContractFee; /// fee of token pair address srcTokenAccount; /// shadow token account bytes destUserAccount; /// account of token destination chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /// @notice struct of Rapidity user burn lock parameters struct RapiditySmgReleaseParams { bytes32 uniqueID; /// Rapidity random number bytes32 smgID; /// ID of storeman group which user has selected uint tokenPairID; /// token pair id on cross chain uint value; /// exchange token value uint fee; /// exchange token fee address destTokenAccount; /// original token/coin account address destUserAccount; /// account of token original chain, used to receive token address smgFeeProxy; /// address of the proxy to store fee for storeman group } /** * * EVENTS * **/ /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity original token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserLockLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint contractFee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param tokenAccount Rapidity shadow token account /// @param value Rapidity value /// @param userAccount account of shadow chain, used to receive token event UserBurnLogger(bytes32 indexed smgID, uint indexed tokenPairID, address indexed tokenAccount, uint value, uint contractFee, uint fee, bytes userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param fee Rapidity fee /// @param tokenAccount Rapidity shadow token account /// @param userAccount account of original chain, used to receive token event SmgMintLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, uint fee, address tokenAccount, address userAccount); /// @notice event of exchange WRC-20 token with original chain token request /// @notice event invoked by storeman group /// @param uniqueID unique random number /// @param smgID ID of storemanGroup /// @param tokenPairID token pair ID of cross chain token /// @param value Rapidity value /// @param fee Rapidity fee /// @param tokenAccount Rapidity original token account /// @param userAccount account of original chain, used to receive token event SmgReleaseLogger(bytes32 indexed uniqueID, bytes32 indexed smgID, uint indexed tokenPairID, uint value, uint fee, address tokenAccount, address userAccount); /** * * MANIPULATIONS * */ /// @notice mintBridge, user lock token on token original chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for user mint lock token on token original chain function userLock(CrossTypesV1.Data storage storageData, RapidityUserLockParams memory params) public { uint fromChainID; uint toChainID; bytes memory fromTokenAccount; (fromChainID,fromTokenAccount,toChainID) = storageData.tokenManager.getTokenPairInfoSlim(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); uint contractFee = params.tokenPairContractFee; if (contractFee == 0) { contractFee = storageData.mapContractFee[fromChainID][toChainID]; } if (contractFee > 0) { params.smgFeeProxy.transfer(contractFee); } address tokenScAddr = CrossTypesV1.bytesToAddress(fromTokenAccount); uint left; if (tokenScAddr == address(0)) { left = (msg.value).sub(params.value).sub(contractFee); } else { left = (msg.value).sub(contractFee); uint8 tokenCrossType = storageData.tokenManager.mapTokenPairType(params.tokenPairID); if (tokenCrossType == uint8(TokenCrossType.ERC20)) { require(CrossTypesV1.transferFrom(tokenScAddr, msg.sender, address(this), params.value), "Lock token failed"); } else if (tokenCrossType == uint8(TokenCrossType.ERC721)) { IERC721(tokenScAddr).safeTransferFrom(msg.sender, address(this), params.value); } else { require(false, "Not support"); } } if (left != 0) { (msg.sender).transfer(left); } emit UserLockLogger(params.smgID, params.tokenPairID, tokenScAddr, params.value, contractFee, params.destUserAccount); } /// @notice burnBridge, user lock token on token original chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for user burn lock token on token original chain function userBurn(CrossTypesV1.Data storage storageData, RapidityUserBurnParams memory params) public { ITokenManager tokenManager = storageData.tokenManager; uint fromChainID; uint toChainID; bytes memory fromTokenAccount; bytes memory toTokenAccount; (fromChainID,fromTokenAccount,toChainID,toTokenAccount) = tokenManager.getTokenPairInfo(params.tokenPairID); require(fromChainID != 0, "Token does not exist"); uint256 contractFee = params.tokenPairContractFee; address tokenScAddr; if (params.currentChainID == toChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[toChainID][fromChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(toTokenAccount); } else if (params.currentChainID == fromChainID) { if (contractFee == 0) { contractFee = storageData.mapContractFee[fromChainID][toChainID]; } tokenScAddr = CrossTypesV1.bytesToAddress(fromTokenAccount); } else { require(false, "Invalid token pair"); } require(params.srcTokenAccount == tokenScAddr, "Invalid token account"); // Reuse variable fromChainID as tokenCrossType; burn token by tokenCrossType fromChainID = tokenManager.mapTokenPairType(params.tokenPairID); if (fromChainID == uint8(TokenCrossType.ERC20)) { require(burnShadowToken(tokenManager, tokenScAddr, msg.sender, params.value), "Burn failed"); } else if (fromChainID == uint8(TokenCrossType.ERC721)) { require(burnShadowNftToken(tokenManager, tokenScAddr, msg.sender, params.value), "Burn NFT failed"); } else { require(false, "Not support"); } if (contractFee > 0) { params.smgFeeProxy.transfer(contractFee); } uint left = (msg.value).sub(contractFee); if (left != 0) { (msg.sender).transfer(left); } emit UserBurnLogger(params.smgID, params.tokenPairID, tokenScAddr, params.value, contractFee, params.fee, params.destUserAccount); } /// @notice mintBridge, storeman mint lock token on token shadow chain /// @notice event invoked by user mint lock /// @param storageData Cross storage data /// @param params parameters for storeman mint lock token on token shadow chain function smgMint(CrossTypesV1.Data storage storageData, RapiditySmgMintParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); ITokenManager tokenManager = storageData.tokenManager; uint8 tokenCrossType = tokenManager.mapTokenPairType(params.tokenPairID); if (tokenCrossType == uint8(TokenCrossType.ERC20)) { if (params.fee > 0) { require(mintShadowToken(tokenManager, params.destTokenAccount, params.smgFeeProxy, params.fee), "Mint fee failed"); } require(mintShadowToken(tokenManager, params.destTokenAccount, params.destUserAccount, params.value), "Mint failed"); } else if (tokenCrossType == uint8(TokenCrossType.ERC721)) { require(mintShadowNftToken(tokenManager, params.destTokenAccount, params.destUserAccount, params.value), "Mint NFT failed"); } else { require(false, "Not support"); } emit SmgMintLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.fee, params.destTokenAccount, params.destUserAccount); } /// @notice burnBridge, storeman burn lock token on token shadow chain /// @notice event invoked by user burn lock /// @param storageData Cross storage data /// @param params parameters for storeman burn lock token on token shadow chain function smgRelease(CrossTypesV1.Data storage storageData, RapiditySmgReleaseParams memory params) public { storageData.rapidityTxData.addRapidityTx(params.uniqueID); if (params.destTokenAccount == address(0)) { (params.destUserAccount).transfer(params.value); if (params.fee > 0) { params.smgFeeProxy.transfer(params.fee); } } else { uint8 tokenCrossType = storageData.tokenManager.mapTokenPairType(params.tokenPairID); if (tokenCrossType == uint8(TokenCrossType.ERC20)) { if (params.fee > 0) { require(CrossTypesV1.transfer(params.destTokenAccount, params.smgFeeProxy, params.fee), "Transfer token fee failed"); } require(CrossTypesV1.transfer(params.destTokenAccount, params.destUserAccount, params.value), "Transfer token failed"); } else if (tokenCrossType == uint8(TokenCrossType.ERC721)) { IERC721(params.destTokenAccount).safeTransferFrom(address(this), params.destUserAccount, params.value); } else { require(false, "Not support"); } } emit SmgReleaseLogger(params.uniqueID, params.smgID, params.tokenPairID, params.value, params.fee, params.destTokenAccount, params.destUserAccount); } function burnShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).burnToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.sub(value); } function mintShadowToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).mintToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.add(value); } function burnShadowNftToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).burnToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.sub(1); } function mintShadowNftToken(address tokenManager, address tokenAddress, address userAccount, uint value) private returns (bool) { uint beforeBalance; uint afterBalance; beforeBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); ITokenManager(tokenManager).mintToken(tokenAddress, userAccount, value); afterBalance = IRC20Protocol(tokenAddress).balanceOf(userAccount); return afterBalance == beforeBalance.add(1); } function addressToBytes32(address a) private pure returns (bytes32) { return bytes32(uint256(uint160(a))); } }
contracts/interfaces/IMetric.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.24; interface IMetric { // index of array: smIndex function getPrdInctMetric(bytes32 grpId, uint startEpId, uint endEpId) external returns(uint[]); function getPrdSlshMetric(bytes32 grpId, uint startEpId, uint endEpId) external returns(uint[]); function getSmSuccCntByEpId(bytes32 grpId, uint epId, uint8 smIndex) external returns(uint); function getSlshCntByEpId(bytes32 grpId, uint epId, uint8 smIndex) external returns(uint); }
contracts/interfaces/IRC20Protocol.sol
/* Copyright 2019 Wanchain 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. */ // _ _ _ // __ ____ _ _ __ ___| |__ __ _(_)_ __ __| | _____ __ // \ \ /\ / / _` | '_ \ / __| '_ \ / _` | | '_ \@/ _` |/ _ \ \ / / // \ V V / (_| | | | | (__| | | | (_| | | | | | (_| | __/\ V / // \_/\_/ \__,_|_| |_|\___|_| |_|\__,_|_|_| |_|\__,_|\___| \_/ // // pragma solidity ^0.4.26; interface IRC20Protocol { function transfer(address, uint) external returns (bool); function transferFrom(address, address, uint) external returns (bool); function balanceOf(address _owner) external view returns (uint); }
Contract ABI
[{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeAdmin","inputs":[{"type":"address","name":"admin"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"burnNFT","inputs":[{"type":"uint256","name":"tokenCrossType"},{"type":"address","name":"tokenAddress"},{"type":"address","name":"from"},{"type":"uint256[]","name":"tokenIDs"},{"type":"uint256[]","name":"values"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"removeTokenPair","inputs":[{"type":"uint256","name":"id"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"burnToken","inputs":[{"type":"address","name":"tokenAddress"},{"type":"address","name":"from"},{"type":"uint256","name":"value"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"fromChainID"},{"type":"bytes","name":"fromAccount"},{"type":"uint256","name":"toChainID"}],"name":"getTokenPairInfoSlim","inputs":[{"type":"uint256","name":"id"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"acceptTokenOwnership","inputs":[{"type":"address","name":"tokenAddress"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferTokenOwner","inputs":[{"type":"address","name":"tokenAddress"},{"type":"address","name":"_newOwner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"changeTokenOwner","inputs":[{"type":"address","name":"tokenAddress"},{"type":"address","name":"_newOwner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addTokenPair","inputs":[{"type":"uint256","name":"id"},{"type":"tuple","name":"aInfo","components":[{"type":"bytes","name":"account"},{"type":"string","name":"name"},{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"},{"type":"uint256","name":"chainID"}]},{"type":"uint256","name":"fromChainID"},{"type":"bytes","name":"fromAccount"},{"type":"uint256","name":"toChainID"},{"type":"bytes","name":"toAccount"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"transferOwner","inputs":[{"type":"address","name":"_newOwner"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":"id"},{"type":"uint256[]","name":"fromChainID"},{"type":"bytes[]","name":"fromAccount"},{"type":"uint256[]","name":"toChainID"},{"type":"bytes[]","name":"toAccount"},{"type":"string[]","name":"ancestorSymbol"},{"type":"uint8[]","name":"ancestorDecimals"},{"type":"bytes[]","name":"ancestorAccount"},{"type":"string[]","name":"ancestorName"},{"type":"uint256[]","name":"ancestorChainID"}],"name":"getTokenPairsByChainID","inputs":[{"type":"uint256","name":"chainID1"},{"type":"uint256","name":"chainID2"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"operator","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"mapTokenPairIndex","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"implementation","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"tuple","name":"aInfo","components":[{"type":"bytes","name":"account"},{"type":"string","name":"name"},{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"},{"type":"uint256","name":"chainID"}]},{"type":"uint256","name":"fromChainID"},{"type":"bytes","name":"fromAccount"},{"type":"uint256","name":"toChainID"},{"type":"bytes","name":"toAccount"}],"name":"mapTokenPairInfo","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"mintToken","inputs":[{"type":"address","name":"tokenAddress"},{"type":"address","name":"to"},{"type":"uint256","name":"value"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"updateTokenPair","inputs":[{"type":"uint256","name":"id"},{"type":"tuple","name":"aInfo","components":[{"type":"bytes","name":"account"},{"type":"string","name":"name"},{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"},{"type":"uint256","name":"chainID"}]},{"type":"uint256","name":"fromChainID"},{"type":"bytes","name":"fromAccount"},{"type":"uint256","name":"toChainID"},{"type":"bytes","name":"toAccount"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addAdmin","inputs":[{"type":"address","name":"admin"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"renounceOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint8","name":""}],"name":"mapTokenPairType","inputs":[{"type":"uint256","name":""}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"acceptOwnership","inputs":[],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"addr"},{"type":"string","name":"name"},{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"}],"name":"getTokenInfo","inputs":[{"type":"uint256","name":"id"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"owner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes","name":"account"},{"type":"string","name":"name"},{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"},{"type":"uint256","name":"chainId"}],"name":"getAncestorInfo","inputs":[{"type":"uint256","name":"id"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"mintNFT","inputs":[{"type":"uint256","name":"tokenCrossType"},{"type":"address","name":"tokenAddress"},{"type":"address","name":"to"},{"type":"uint256[]","name":"tokenIDs"},{"type":"uint256[]","name":"values"},{"type":"bytes","name":"data"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"changeOwner","inputs":[{"type":"address","name":"_newOwner"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"updateToken","inputs":[{"type":"address","name":"tokenAddress"},{"type":"string","name":"name"},{"type":"string","name":"symbol"}],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setOperator","inputs":[{"type":"address","name":"account"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"fromChainID"},{"type":"bytes","name":"fromAccount"},{"type":"uint256","name":"toChainID"},{"type":"bytes","name":"toAccount"}],"name":"getTokenPairInfo","inputs":[{"type":"uint256","name":"id"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setTokenPairTypes","inputs":[{"type":"uint256[]","name":"tokenPairIds"},{"type":"uint8[]","name":"tokenPairTypes"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":""}],"name":"totalTokenPairs","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":""}],"name":"newOwner","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":""}],"name":"mapAdmin","inputs":[{"type":"address","name":""}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"}],"name":"getAncestorSymbol","inputs":[{"type":"uint256","name":"id"}],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256[]","name":"id"},{"type":"uint256[]","name":"fromChainID"},{"type":"bytes[]","name":"fromAccount"},{"type":"uint256[]","name":"toChainID"},{"type":"bytes[]","name":"toAccount"},{"type":"string[]","name":"ancestorSymbol"},{"type":"uint8[]","name":"ancestorDecimals"},{"type":"bytes[]","name":"ancestorAccount"},{"type":"string[]","name":"ancestorName"},{"type":"uint256[]","name":"ancestorChainID"}],"name":"getTokenPairs","inputs":[],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"addToken","inputs":[{"type":"string","name":"name"},{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"uint256","name":"chainID"}],"name":"getAncestorChainID","inputs":[{"type":"uint256","name":"id"}],"constant":true},{"type":"fallback","stateMutability":"payable","payable":true},{"type":"event","name":"SetOperator","inputs":[{"type":"address","name":"oldOperator","indexed":true},{"type":"address","name":"newOperator","indexed":true}],"anonymous":false},{"type":"event","name":"SetTokenPairType","inputs":[{"type":"uint256","name":"tokenPairId","indexed":true},{"type":"uint256","name":"tokenPairType","indexed":true}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","indexed":true}],"anonymous":false},{"type":"event","name":"AddToken","inputs":[{"type":"address","name":"tokenAddress","indexed":false},{"type":"string","name":"name","indexed":false},{"type":"string","name":"symbol","indexed":false},{"type":"uint8","name":"decimals","indexed":false}],"anonymous":false},{"type":"event","name":"AddTokenPair","inputs":[{"type":"uint256","name":"id","indexed":true},{"type":"uint256","name":"fromChainID","indexed":false},{"type":"bytes","name":"fromAccount","indexed":false},{"type":"uint256","name":"toChainID","indexed":false},{"type":"bytes","name":"toAccount","indexed":false}],"anonymous":false},{"type":"event","name":"UpdateTokenPair","inputs":[{"type":"uint256","name":"id","indexed":true},{"type":"tuple","name":"aInfo","indexed":false,"components":[{"type":"bytes","name":"account"},{"type":"string","name":"name"},{"type":"string","name":"symbol"},{"type":"uint8","name":"decimals"},{"type":"uint256","name":"chainID"}]},{"type":"uint256","name":"fromChainID","indexed":false},{"type":"bytes","name":"fromAccount","indexed":false},{"type":"uint256","name":"toChainID","indexed":false},{"type":"bytes","name":"toAccount","indexed":false}],"anonymous":false},{"type":"event","name":"RemoveTokenPair","inputs":[{"type":"uint256","name":"id","indexed":true}],"anonymous":false},{"type":"event","name":"UpdateToken","inputs":[{"type":"address","name":"tokenAddress","indexed":false},{"type":"string","name":"name","indexed":false},{"type":"string","name":"symbol","indexed":false}],"anonymous":false},{"type":"event","name":"AddAdmin","inputs":[{"type":"address","name":"admin","indexed":false}],"anonymous":false},{"type":"event","name":"RemoveAdmin","inputs":[{"type":"address","name":"admin","indexed":false}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","indexed":true},{"type":"address","name":"newOwner","indexed":true}],"anonymous":false}]
Contract Creation Code
0x6080604052600060055560088054600160a060020a0319163317905561573a8061002a6000396000f300608060405260043610620001d95763ffffffff60e060020a6000350416631785f53c8114620002395780632859c58014620002605780632b56590514620002855780633416794d14620002aa5780633ad8873a14620002cf5780633cc281df146200030e578063408e743d146200033357806341246e5314620003585780634f600ae8146200037d5780634fb2e45d14620003a2578063563cb1ab14620003c7578063570ca735146200040457806358a007fb146200042b5780635c60da1b146200045f5780635d2e9ead14620004775780636bec32da14620004af5780636c45e2dc14620004d45780637048027514620004f9578063715018a6146200051e57806375d2e27d146200053657806379ba5097146200056a5780638c7a63ae14620005825780638da5cb5b14620005b95780639027e6f714620005d15780639947f9321462000609578063a6f9dae1146200062e578063af33f17e1462000653578063b3ab15fb1462000678578063b9073276146200069d578063cbfbd61a14620006d4578063d0ad718d14620006f9578063d4ee1d901462000711578063d51dddd71462000729578063e101d3c1146200075d578063e24e4fdb1462000792578063f3bdd86314620007aa578063f4debe1e14620007cf575b600b54600160a060020a0316801515620002135760405160e560020a62461bcd0281526004016200020a9062004436565b60405180910390fd5b60405136600082376000803683855af43d806000843e81801562000235578184f35b8184fd5b3480156200024657600080fd5b506200025e6200025836600462003693565b620007f4565b005b3480156200026d57600080fd5b506200025e6200027f3660046200393f565b62000881565b3480156200029257600080fd5b506200025e620002a43660046200391e565b620009be565b348015620002b757600080fd5b506200025e620002c9366004620036fb565b62000b66565b348015620002dc57600080fd5b50620002f4620002ee3660046200391e565b62000c1f565b604051620003059392919062004521565b60405180910390f35b3480156200031b57600080fd5b506200025e6200032d36600462003693565b62000ce0565b3480156200034057600080fd5b506200025e62000352366004620036bc565b62000d34565b3480156200036557600080fd5b506200025e62000377366004620036bc565b62000de3565b3480156200038a57600080fd5b506200025e6200039c36600462003ac3565b62000e5a565b348015620003af57600080fd5b506200025e620003c136600462003693565b62001046565b348015620003d457600080fd5b50620003ec620003e636600462003b69565b6200110d565b604051620003059a999897969594939291906200422c565b3480156200041157600080fd5b506200041c620018f7565b6040516200030591906200401d565b3480156200043857600080fd5b50620004506200044a3660046200391e565b62001906565b60405162000305919062004511565b3480156200046c57600080fd5b506200041c62001918565b3480156200048457600080fd5b506200049c620004963660046200391e565b62001928565b60405162000305959493929190620044b4565b348015620004bc57600080fd5b506200025e620004ce366004620036fb565b62001c68565b348015620004e157600080fd5b506200025e620004f336600462003ac3565b62001ce8565b3480156200050657600080fd5b506200025e6200051836600462003693565b62001e8a565b3480156200052b57600080fd5b506200025e62001f0f565b3480156200054357600080fd5b506200055b620005553660046200391e565b62001f5e565b6040516200030591906200459f565b3480156200057757600080fd5b506200025e62001f73565b3480156200058f57600080fd5b50620005a7620005a13660046200391e565b62001fb9565b604051620003059493929190620041c2565b348015620005c657600080fd5b506200041c62002239565b348015620005de57600080fd5b50620005f6620005f03660046200391e565b62002248565b6040516200030595949392919062004328565b3480156200061657600080fd5b506200025e62000628366004620039e4565b62002462565b3480156200063b57600080fd5b506200025e6200064d36600462003693565b6200257f565b3480156200066057600080fd5b506200025e620006723660046200374f565b620025de565b3480156200068557600080fd5b506200025e6200069736600462003693565b620026d7565b348015620006aa57600080fd5b50620006c2620006bc3660046200391e565b62002770565b60405162000305949392919062004556565b348015620006e157600080fd5b506200025e620006f3366004620037df565b620028d1565b3480156200070657600080fd5b5062000450620029f4565b3480156200071e57600080fd5b506200041c620029fa565b3480156200073657600080fd5b506200074e6200074836600462003693565b62002a09565b60405162000305919062004318565b3480156200076a57600080fd5b50620007826200077c3660046200391e565b62002a1e565b60405162000305929190620043ee565b3480156200079f57600080fd5b50620003ec62002ae1565b348015620007b757600080fd5b506200025e620007c936600462003856565b620031d3565b348015620007dc57600080fd5b5062000450620007ee3660046200391e565b62003290565b600854600160a060020a03163314620008245760405160e560020a62461bcd0281526004016200020a906200446c565b600160a060020a0381166000908152600a602052604090819020805460ff19169055517f753f40ca3312b2408759a67875b367955e7baa221daf08aa3d643d96202ac12b90620008769083906200401d565b60405180910390a150565b336000908152600a602052604090205460ff161515620008b85760405160e560020a62461bcd0281526004016200020a9062004490565b600185141562000945576040517fb2dc5dc3000000000000000000000000000000000000000000000000000000008152600160a060020a0385169063b2dc5dc3906200090b908690869060040162004033565b600060405180830381600087803b1580156200092657600080fd5b505af11580156200093b573d6000803e3d6000fd5b50505050620009b7565b60028514156200099a576040517f6b20c454000000000000000000000000000000000000000000000000000000008152600160a060020a03851690636b20c454906200090b9086908690869060040162004057565b60405160e560020a62461bcd0281526004016200020a906200447e565b5050505050565b600854600090600160a060020a03163314620009f15760405160e560020a62461bcd0281526004016200020a906200446c565b60008281526006602052604081206005015483911062000a285760405160e560020a62461bcd0281526004016200020a906200445a565b600091505b60055482101562000b615760008281526007602052604090205483141562000b555760055460001901821462000a7b5760055460001901600090815260076020526040808220548483529120555b60058054600019908101600090815260076020908152604080832083905584549093019093558581526006909252812090818162000aba8282620032c6565b62000aca600183016000620032c6565b62000ada600283016000620032c6565b5060038101805460ff19169055600060049091018190556005830181905562000b08906006840190620032c6565b600782016000905560088201600062000b229190620032c6565b505060405183907fa219112a711e6173c2e8978836823d4e86832d96c0ea2fd05ec77687b7a073ab90600090a262000b61565b60019091019062000a2d565b505050565b336000908152600a602052604090205460ff16151562000b9d5760405160e560020a62461bcd0281526004016200020a9062004490565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152600160a060020a03841690639dc29fac9062000be690859085906004016200420d565b600060405180830381600087803b15801562000c0157600080fd5b505af115801562000c16573d6000803e3d6000fd5b50505050505050565b60008181526006602081815260408084206005810154930180548251601f600260001961010060018616150201909316929092049182018590048502810185019093528083529394606094909383018282801562000cc15780601f1062000c955761010080835404028352916020019162000cc1565b820191906000526020600020905b81548152906001019060200180831162000ca357829003601f168201915b5050506000968752505060066020526040909420600701549294915050565b80600160a060020a03166379ba50976040518163ffffffff1660e060020a028152600401600060405180830381600087803b15801562000d1f57600080fd5b505af1158015620009b7573d6000803e3d6000fd5b600854600160a060020a0316331462000d645760405160e560020a62461bcd0281526004016200020a906200446c565b6040517f4fb2e45d000000000000000000000000000000000000000000000000000000008152600160a060020a03831690634fb2e45d9062000dab9084906004016200401d565b600060405180830381600087803b15801562000dc657600080fd5b505af115801562000ddb573d6000803e3d6000fd5b505050505050565b600854600160a060020a0316331462000e135760405160e560020a62461bcd0281526004016200020a906200446c565b6040517fa6f9dae1000000000000000000000000000000000000000000000000000000008152600160a060020a0383169063a6f9dae19062000dab9084906004016200401d565b600854600160a060020a0316331462000e8a5760405160e560020a62461bcd0281526004016200020a906200446c565b60008681526006602052604090206005015486901562000ec15760405160e560020a62461bcd0281526004016200020a9062004424565b600087815260066020818152604090922060058101889055865162000eef9391909201919087019062003311565b50600087815260066020908152604090912060078101859055835162000f1e9260089092019185019062003311565b5085516000888152600660209081526040909120825162000f459391929091019062003311565b5060208087015160008981526006835260409020815162000f70936001909201929091019062003311565b50604080870151600089815260066020908152929020815162000f9e93600290920192919091019062003311565b506060860151600088815260066020908152604080832060038101805460ff191660ff9096169590951790945560808a015160049094019390935560058054835260079091529190208890555462000ff8906001620032a5565b60055560405187907f226f08da880957e11c8affd4d622bb21b058cf67830d2ee56bb82d9b7197e9a7906200103590889088908890889062004556565b60405180910390a250505050505050565b600854600160a060020a03163314620010765760405160e560020a62461bcd0281526004016200020a906200446c565b600160a060020a0381161515620010a45760405160e560020a62461bcd0281526004016200020a9062004448565b600854604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b606080606080606080606080606080600080600060606000935060009250600091506005546040519080825280602002602001820160405280156200115c578160200160208202803883390190505b5090505b6005548310156200122757600760008481526020019081526020016000205491508f6006600084815260200190815260200160002060050154148015620011b757506000828152600660205260409020600701548f145b80620011f457508f6006600084815260200190815260200160002060070154148015620011f457506000828152600660205260409020600501548f145b156200121b578181858151811015156200120a57fe5b602090810290910101526001909301925b60019092019162001160565b8360405190808252806020026020018201604052801562001252578160200160208202803883390190505b509d508360405190808252806020026020018201604052801562001280578160200160208202803883390190505b509c5083604051908082528060200260200182016040528015620012b957816020015b6060815260200190600190039081620012a35790505b509b5083604051908082528060200260200182016040528015620012e7578160200160208202803883390190505b509a50836040519080825280602002602001820160405280156200132057816020015b60608152602001906001900390816200130a5790505b509950836040519080825280602002602001820160405280156200135957816020015b6060815260200190600190039081620013435790505b5098508360405190808252806020026020018201604052801562001387578160200160208202803883390190505b50975083604051908082528060200260200182016040528015620013c057816020015b6060815260200190600190039081620013aa5790505b50965083604051908082528060200260200182016040528015620013f957816020015b6060815260200190600190039081620013e35790505b5095508360405190808252806020026020018201604052801562001427578160200160208202803883390190505b509450600092505b83831015620018e45780838151811015156200144757fe5b906020019060200201519150818e848151811015156200146357fe5b60209081029091018101919091526000838152600690915260409020600501548d518e90859081106200149257fe5b60209081029190910181019190915260008381526006808352604091829020018054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015620015385780601f106200150c5761010080835404028352916020019162001538565b820191906000526020600020905b8154815290600101906020018083116200151a57829003601f168201915b50505050508c848151811015156200154c57fe5b60209081029091018101919091526000838152600690915260409020600701548b518c90859081106200157b57fe5b6020908102919091018101919091526000838152600682526040908190206008018054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015620016225780601f10620015f65761010080835404028352916020019162001622565b820191906000526020600020905b8154815290600101906020018083116200160457829003601f168201915b50505050508a848151811015156200163657fe5b6020908102909101810191909152600083815260068252604090819020600290810180548351601f60001961010060018516150201909216939093049081018590048502830185019093528282529092909190830182828015620016de5780601f10620016b257610100808354040283529160200191620016de565b820191906000526020600020905b815481529060010190602001808311620016c057829003601f168201915b50505050508984815181101515620016f257fe5b6020908102909101810191909152600083815260069091526040902060030154885160ff909116908990859081106200172757fe5b60ff909216602092830290910182015260008381526006825260409081902080548251601f600260001961010060018616150201909316929092049182018590048502810185019093528083529192909190830182828015620017ce5780601f10620017a257610100808354040283529160200191620017ce565b820191906000526020600020905b815481529060010190602001808311620017b057829003601f168201915b50505050508784815181101515620017e257fe5b602090810291909101810191909152600083815260068252604090819020600190810180548351600293821615610100026000190190911692909204601f810185900485028301850190935282825290929091908301828280156200188b5780601f106200185f576101008083540402835291602001916200188b565b820191906000526020600020905b8154815290600101906020018083116200186d57829003601f168201915b505050505086848151811015156200189f57fe5b60209081029091018101919091526000838152600690915260409020600401548551869085908110620018ce57fe5b602090810290910101526001909201916200142f565b505050509295989b9194979a5092959850565b600c54600160a060020a031681565b60076020526000908152604090205481565b600b54600160a060020a03165b90565b6006602090815260009182526040918290208251815460026001821615610100026000190190911604601f8101849004909302810160c090810190945260a08101838152919390928492849290918491840182828015620019cd5780601f10620019a157610100808354040283529160200191620019cd565b820191906000526020600020905b815481529060010190602001808311620019af57829003601f168201915b50505050508152602001600182018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801562001a735780601f1062001a475761010080835404028352916020019162001a73565b820191906000526020600020905b81548152906001019060200180831162001a5557829003601f168201915b5050509183525050600282810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452938101939083018282801562001b095780601f1062001add5761010080835404028352916020019162001b09565b820191906000526020600020905b81548152906001019060200180831162001aeb57829003601f168201915b5050509183525050600382015460ff1660208083019190915260049092015460409182015260058401546006850180548351601f6002600019600185161561010002019093169290920491820186900486028101860190945280845294959194919390919083018282801562001bc35780601f1062001b975761010080835404028352916020019162001bc3565b820191906000526020600020905b81548152906001019060200180831162001ba557829003601f168201915b50505050600783015460088401805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152959693959394509083018282801562001c5e5780601f1062001c325761010080835404028352916020019162001c5e565b820191906000526020600020905b81548152906001019060200180831162001c4057829003601f168201915b5050505050905085565b336000908152600a602052604090205460ff16151562001c9f5760405160e560020a62461bcd0281526004016200020a9062004490565b6040517f40c10f19000000000000000000000000000000000000000000000000000000008152600160a060020a038416906340c10f199062000be690859085906004016200420d565b600854600160a060020a0316331462001d185760405160e560020a62461bcd0281526004016200020a906200446c565b60008681526006602052604081206005015487911062001d4f5760405160e560020a62461bcd0281526004016200020a906200445a565b85516000888152600660209081526040909120825162001d759391929091019062003311565b5060208087015160008981526006835260409020815162001da0936001909201929091019062003311565b50604080870151600089815260066020908152929020815162001dce93600290920192919091019062003311565b506060860151600088815260066020818152604090922060038101805460ff191660ff909516949094179093556080890151600484015560058301889055865162001e20939091019187019062003311565b50600087815260066020908152604090912060078101859055835162001e4f9260089092019185019062003311565b50867f4eb0f9fb05e08613a2eba9dc272a43421cf32f9ccab592725ab663e3238f5f55878787878760405162001035959493929190620044b4565b600854600160a060020a0316331462001eba5760405160e560020a62461bcd0281526004016200020a906200446c565b600160a060020a0381166000908152600a602052604090819020805460ff19166001179055517fad6de4452a631e641cb59902236607946ce9272b9b981f2f80e8d129cb9084ba90620008769083906200401d565b600854600160a060020a0316331462001f3f5760405160e560020a62461bcd0281526004016200020a906200446c565b6008805473ffffffffffffffffffffffffffffffffffffffff19169055565b600d6020526000908152604090205460ff1681565b600954600160a060020a031633141562001fb7576009546008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555b565b600081815260066020526040812060050154606090819083908190151562002006576040805160208181018352600080835283519182019093528281529196509450925084915062002231565b60008681526006602090815260409182902060080180548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452620020af9392830182828015620020a45780601f106200207857610100808354040283529160200191620020a4565b820191906000526020600020905b8154815290600101906020018083116200208657829003601f168201915b5050505050620032bf565b905080600160a060020a03166306fdde036040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015620020f057600080fd5b505af115801562002105573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200212f9190810190620038e5565b935080600160a060020a03166395d89b416040518163ffffffff1660e060020a028152600401600060405180830381600087803b1580156200217057600080fd5b505af115801562002185573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620021af9190810190620038e5565b925080600160a060020a031663313ce5676040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620021f057600080fd5b505af115801562002205573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506200222b919081019062003b9e565b91508094505b509193509193565b600854600160a060020a031681565b600081815260066020908152604080832080548251601f6002600019610100600186161502019093169290920491820185900485028101850190935280835260609485948594919384939091830182828015620022e95780601f10620022bd57610100808354040283529160200191620022e9565b820191906000526020600020905b815481529060010190602001808311620022cb57829003601f168201915b505050600089815260066020908152604091829020600190810180548451600293821615610100026000190190911692909204601f8101849004840283018401909452838252959a509493509091508301828280156200238d5780601f1062002361576101008083540402835291602001916200238d565b820191906000526020600020905b8154815290600101906020018083116200236f57829003601f168201915b5050506000898152600660209081526040918290206002908101805484516001821615610100026000190190911692909204601f8101849004840283018401909452838252959950949350909150830182828015620024305780601f10620024045761010080835404028352916020019162002430565b820191906000526020600020905b8154815290600101906020018083116200241257829003601f168201915b50505060009889525050600660205260409096206003810154600490910154959794969560ff90911694909350915050565b336000908152600a602052604090205460ff161515620024995760405160e560020a62461bcd0281526004016200020a9062004490565b600186141562002528576040517f22862482000000000000000000000000000000000000000000000000000000008152600160a060020a03861690632286248290620024ee90879087908690600401620040f4565b600060405180830381600087803b1580156200250957600080fd5b505af11580156200251e573d6000803e3d6000fd5b5050505062000ddb565b60028614156200099a576040517f1f7fdffa000000000000000000000000000000000000000000000000000000008152600160a060020a03861690631f7fdffa90620024ee9087908790879087906004016200409a565b600854600160a060020a03163314620025af5760405160e560020a62461bcd0281526004016200020a906200446c565b6009805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600854600160a060020a031633146200260e5760405160e560020a62461bcd0281526004016200020a906200446c565b6040517ff4c84d19000000000000000000000000000000000000000000000000000000008152600160a060020a0386169063f4c84d19906200265b90879087908790879060040162004387565b600060405180830381600087803b1580156200267657600080fd5b505af11580156200268b573d6000803e3d6000fd5b505050507f86ead451719b8f4b763de2648808971e9bf540eed93efadafb044cd7ef5d91f48585858585604051620026c89594939291906200412e565b60405180910390a15050505050565b600854600160a060020a03163314620027075760405160e560020a62461bcd0281526004016200020a906200446c565b600c54604051600160a060020a038084169216907f2709918445f306d3e94d280907c62c5d2525ac3192d2e544774c7f181d65af3e90600090a3600c805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60008181526006602081815260408084206005810154930180548251601f60026000196101006001861615020190931692909204918201859004850281018501909352808352939460609490938593929190830182828015620028175780601f10620027eb5761010080835404028352916020019162002817565b820191906000526020600020905b815481529060010190602001808311620027f957829003601f168201915b505050600088815260066020908152604091829020600781015460089091018054845160026001831615610100026000190190921691909104601f81018590048502820185019095528481529699509097509350909150830182828015620028c35780601f106200289757610100808354040283529160200191620028c3565b820191906000526020600020905b815481529060010190602001808311620028a557829003601f168201915b505050505090509193509193565b600c54600090600160a060020a03163314620029045760405160e560020a62461bcd0281526004016200020a90620044a2565b838214620029295760405160e560020a62461bcd0281526004016200020a9062004412565b5060005b83811015620009b7578282828181106200294357fe5b9050602002013560ff16600d600087878581811015156200296057fe5b90506020020135815260200190815260200160002060006101000a81548160ff021916908360ff16021790555082828281811015156200299c57fe5b9050602002013560ff1660ff168585838181101515620029b857fe5b905060200201357f20f86c53e8884644ce473603799d40ecf47d8c4c1d55384fe8d0eeaf697786eb60405160405180910390a36001016200292d565b60055481565b600954600160a060020a031681565b600a6020526000908152604090205460ff1681565b60008181526006602090815260408083206002908101805483516001821615610100026000190190911692909204601f8101859004850283018501909352828252606094939192909183018282801562002abc5780601f1062002a905761010080835404028352916020019162002abc565b820191906000526020600020905b81548152906001019060200180831162002a9e57829003601f168201915b505050600095865250506006602052604090932060030154929360ff90931692915050565b606080606080606080606080606080600080600080600554935060009250600091508360405190808252806020026020018201604052801562002b2e578160200160208202803883390190505b509d508360405190808252806020026020018201604052801562002b5c578160200160208202803883390190505b509c508360405190808252806020026020018201604052801562002b9557816020015b606081526020019060019003908162002b7f5790505b509b508360405190808252806020026020018201604052801562002bc3578160200160208202803883390190505b509a508360405190808252806020026020018201604052801562002bfc57816020015b606081526020019060019003908162002be65790505b5099508360405190808252806020026020018201604052801562002c3557816020015b606081526020019060019003908162002c1f5790505b5098508360405190808252806020026020018201604052801562002c63578160200160208202803883390190505b5097508360405190808252806020026020018201604052801562002c9c57816020015b606081526020019060019003908162002c865790505b5096508360405190808252806020026020018201604052801562002cd557816020015b606081526020019060019003908162002cbf5790505b5095508360405190808252806020026020018201604052801562002d03578160200160208202803883390190505b5094506000915060009250600090505b600554811015620031c3576000818152600760205260409020548e5190935083908f908490811062002d4157fe5b60209081029091018101919091526000848152600690915260409020600501548d518e908490811062002d7057fe5b60209081029190910181019190915260008481526006808352604091829020018054825160026001831615610100026000190190921691909104601f81018590048502820185019093528281529290919083018282801562002e165780601f1062002dea5761010080835404028352916020019162002e16565b820191906000526020600020905b81548152906001019060200180831162002df857829003601f168201915b50505050508c8381518110151562002e2a57fe5b60209081029091018101919091526000848152600690915260409020600701548b518c908490811062002e5957fe5b6020908102919091018101919091526000848152600682526040908190206008018054825160026001831615610100026000190190921691909104601f81018590048502820185019093528281529290919083018282801562002f005780601f1062002ed45761010080835404028352916020019162002f00565b820191906000526020600020905b81548152906001019060200180831162002ee257829003601f168201915b50505050508a8381518110151562002f1457fe5b6020908102909101810191909152600084815260068252604090819020600290810180548351601f6000196101006001851615020190921693909304908101859004850283018501909352828252909290919083018282801562002fbc5780601f1062002f905761010080835404028352916020019162002fbc565b820191906000526020600020905b81548152906001019060200180831162002f9e57829003601f168201915b5050505050898381518110151562002fd057fe5b6020908102909101810191909152600084815260069091526040902060030154885160ff909116908990849081106200300557fe5b60ff909216602092830290910182015260008481526006825260409081902080548251601f600260001961010060018616150201909316929092049182018590048502810185019093528083529192909190830182828015620030ac5780601f106200308057610100808354040283529160200191620030ac565b820191906000526020600020905b8154815290600101906020018083116200308e57829003601f168201915b50505050508783815181101515620030c057fe5b602090810291909101810191909152600084815260068252604090819020600190810180548351600293821615610100026000190190911692909204601f81018590048502830185019093528282529092909190830182828015620031695780601f106200313d5761010080835404028352916020019162003169565b820191906000526020600020905b8154815290600101906020018083116200314b57829003601f168201915b505050505086838151811015156200317d57fe5b60209081029091018101919091526000848152600690915260409020600401548551869084908110620031ac57fe5b602090810290910101526001918201910162002d13565b5050505090919293949596979899565b600854600090600160a060020a03163314620032065760405160e560020a62461bcd0281526004016200020a906200446c565b85858585856200321562003396565b62003225959493929190620043b2565b604051809103906000f08015801562003242573d6000803e3d6000fd5b5090507fbb5f9980e27ec75b79e41ce422e643c6c0116fd9f599776a72f89032f70fe205818787878787604051620032809695949392919062004175565b60405180910390a1505050505050565b60009081526006602052604090206004015490565b600082820183811015620032b857600080fd5b9392505050565b6014015190565b50805460018160011615610100020316600290046000825580601f10620032ee57506200330e565b601f0160209004906000526020600020908101906200330e9190620033a7565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200335457805160ff191683800117855562003384565b8280016001018555821562003384579182015b828111156200338457825182559160200191906001019062003367565b5062003392929150620033a7565b5090565b604051611074806200468d83390190565b6200192591905b80821115620033925760008155600101620033ae565b6000620032b882356200462c565b600080601f83018413620033e557600080fd5b50813567ffffffffffffffff811115620033fe57600080fd5b6020830191508360208202830111156200341757600080fd5b9250929050565b6000601f820183136200343057600080fd5b8135620034476200344182620045d7565b620045af565b915081818352602084019350602081019050838560208402820111156200346d57600080fd5b60005b838110156200349d578162003486888262003669565b845250602092830192919091019060010162003470565b5050505092915050565b6000601f82018313620034b957600080fd5b8135620034ca6200344182620045f9565b91508082526020830160208301858383011115620034e757600080fd5b620034f483828462004643565b50505092915050565b600080601f830184136200351057600080fd5b50813567ffffffffffffffff8111156200352957600080fd5b6020830191508360018202830111156200341757600080fd5b6000601f820183136200355457600080fd5b8151620035656200344182620045f9565b915080825260208301602083018583830111156200358257600080fd5b620034f48382846200464f565b600060a08284031215620035a257600080fd5b620035ae60a0620045af565b9050813567ffffffffffffffff811115620035c857600080fd5b620035d684828501620034a7565b825250602082013567ffffffffffffffff811115620035f457600080fd5b6200360284828501620034a7565b602083015250604082013567ffffffffffffffff8111156200362357600080fd5b6200363184828501620034a7565b6040830152506060620036478482850162003677565b60608301525060806200365d8482850162003669565b60808301525092915050565b6000620032b8823562001925565b6000620032b882356200463d565b6000620032b882516200463d565b600060208284031215620036a657600080fd5b6000620036b48484620033c4565b949350505050565b60008060408385031215620036d057600080fd5b6000620036de8585620033c4565b9250506020620036f185828601620033c4565b9150509250929050565b6000806000606084860312156200371157600080fd5b60006200371f8686620033c4565b93505060206200373286828701620033c4565b9250506040620037458682870162003669565b9150509250925092565b6000806000806000606086880312156200376857600080fd5b6000620037768888620033c4565b955050602086013567ffffffffffffffff8111156200379457600080fd5b620037a288828901620034fd565b9450945050604086013567ffffffffffffffff811115620037c257600080fd5b620037d088828901620034fd565b92509250509295509295909350565b60008060008060408587031215620037f657600080fd5b843567ffffffffffffffff8111156200380e57600080fd5b6200381c87828801620033d2565b9450945050602085013567ffffffffffffffff8111156200383c57600080fd5b6200384a87828801620033d2565b95989497509550505050565b6000806000806000606086880312156200386f57600080fd5b853567ffffffffffffffff8111156200388757600080fd5b6200389588828901620034fd565b9550955050602086013567ffffffffffffffff811115620038b557600080fd5b620038c388828901620034fd565b93509350506040620038d88882890162003677565b9150509295509295909350565b600060208284031215620038f857600080fd5b815167ffffffffffffffff8111156200391057600080fd5b620036b48482850162003542565b6000602082840312156200393157600080fd5b6000620036b4848462003669565b600080600080600060a086880312156200395857600080fd5b600062003966888862003669565b95505060206200397988828901620033c4565b94505060406200398c88828901620033c4565b935050606086013567ffffffffffffffff811115620039aa57600080fd5b620039b8888289016200341e565b925050608086013567ffffffffffffffff811115620039d657600080fd5b620038d8888289016200341e565b60008060008060008060c08789031215620039fe57600080fd5b600062003a0c898962003669565b965050602062003a1f89828a01620033c4565b955050604062003a3289828a01620033c4565b945050606087013567ffffffffffffffff81111562003a5057600080fd5b62003a5e89828a016200341e565b935050608087013567ffffffffffffffff81111562003a7c57600080fd5b62003a8a89828a016200341e565b92505060a087013567ffffffffffffffff81111562003aa857600080fd5b62003ab689828a01620034a7565b9150509295509295509295565b60008060008060008060c0878903121562003add57600080fd5b600062003aeb898962003669565b965050602087013567ffffffffffffffff81111562003b0957600080fd5b62003b1789828a016200358f565b955050604062003b2a89828a0162003669565b945050606087013567ffffffffffffffff81111562003b4857600080fd5b62003b5689828a01620034a7565b935050608062003a8a89828a0162003669565b6000806040838503121562003b7d57600080fd5b600062003b8b858562003669565b9250506020620036f18582860162003669565b60006020828403121562003bb157600080fd5b6000620036b4848462003685565b62003bca816200462c565b82525050565b600062003bdd8262004628565b8084526020840193508360208202850162003bf88562004622565b60005b8481101562003c3557838303885262003c1683835162003d69565b925062003c238262004622565b60209890980197915060010162003bfb565b50909695505050505050565b600062003c4e8262004628565b8084526020840193508360208202850162003c698562004622565b60005b8481101562003c3557838303885262003c8783835162003d69565b925062003c948262004622565b60209890980197915060010162003c6c565b600062003cb38262004628565b80845260208401935062003cc78362004622565b60005b8281101562003cfd5762003ce086835162004007565b62003ceb8262004622565b60209690960195915060010162003cca565b5093949350505050565b600062003d148262004628565b80845260208401935062003d288362004622565b60005b8281101562003cfd5762003d4186835162004012565b62003d4c8262004622565b60209690960195915060010162003d2b565b62003bca8162004638565b600062003d768262004628565b80845262003d8c8160208601602086016200464f565b62003d978162004682565b9093016020019392505050565b600082845260208401935062003dbc83858462004643565b62003dc78362004682565b9093019392505050565b600f81527f6c656e677468206d69736d617463680000000000000000000000000000000000602082015260400190565b600b81527f746f6b656e206578697374000000000000000000000000000000000000000000602082015260400190565b601f81527f696d706c656d656e746174696f6e20636f6e7472616374206e6f742073657400602082015260400190565b601d81527f4e6577206f776e657220697320746865207a65726f2061646472657373000000602082015260400190565b600f81527f746f6b656e206e6f742065786973740000000000000000000000000000000000602082015260400190565b600981527f4e6f74206f776e65720000000000000000000000000000000000000000000000602082015260400190565b601081527f496e76616c6964204e4654207479706500000000000000000000000000000000602082015260400190565b600981527f6e6f742061646d696e0000000000000000000000000000000000000000000000602082015260400190565b600c81527f6e6f74206f70657261746f720000000000000000000000000000000000000000602082015260400190565b805160a08084526000919084019062003f9b828262003d69565b9150506020830151848203602086015262003fb7828262003d69565b9150506040830151848203604086015262003fd3828262003d69565b915050606083015162003fea606086018262004012565b50608083015162003fff608086018262004007565b509392505050565b62003bca8162001925565b62003bca816200463d565b602081016200402d828462003bbf565b92915050565b6040810162004043828562003bbf565b8181036020830152620036b4818462003ca6565b6060810162004067828662003bbf565b81810360208301526200407b818562003ca6565b9050818103604083015262004091818462003ca6565b95945050505050565b60808101620040aa828762003bbf565b8181036020830152620040be818662003ca6565b90508181036040830152620040d4818562003ca6565b90508181036060830152620040ea818462003d69565b9695505050505050565b6060810162004104828662003bbf565b818103602083015262004118818562003ca6565b9050818103604083015262004091818462003d69565b606081016200413e828862003bbf565b81810360208301526200415381868862003da4565b905081810360408301526200416a81848662003da4565b979650505050505050565b6080810162004185828962003bbf565b81810360208301526200419a81878962003da4565b90508181036040830152620041b181858762003da4565b90506200416a606083018462004012565b60808101620041d2828762003bbf565b8181036020830152620041e6818662003d69565b90508181036040830152620041fc818562003d69565b905062004091606083018462004012565b604081016200421d828562003bbf565b620032b8602083018462004007565b610140808252810162004240818d62003ca6565b9050818103602083015262004256818c62003ca6565b905081810360408301526200426c818b62003bd0565b9050818103606083015262004282818a62003ca6565b9050818103608083015262004298818962003bd0565b905081810360a0830152620042ae818862003c41565b905081810360c0830152620042c4818762003d07565b905081810360e0830152620042da818662003bd0565b9050818103610100830152620042f1818562003c41565b905081810361012083015262004308818462003ca6565b9c9b505050505050505050505050565b602081016200402d828462003d5e565b60a080825281016200433b818862003d69565b9050818103602083015262004351818762003d69565b9050818103604083015262004367818662003d69565b905062004378606083018562004012565b620040ea608083018462004007565b604080825281016200439b81868862003da4565b90508181036020830152620040ea81848662003da4565b60608082528101620043c681878962003da4565b90508181036020830152620043dd81858762003da4565b9050620040ea604083018462004012565b6040808252810162004401818562003d69565b9050620032b8602083018462004012565b602080825281016200402d8162003dd1565b602080825281016200402d8162003e01565b602080825281016200402d8162003e31565b602080825281016200402d8162003e61565b602080825281016200402d8162003e91565b602080825281016200402d8162003ec1565b602080825281016200402d8162003ef1565b602080825281016200402d8162003f21565b602080825281016200402d8162003f51565b60a08082528101620044c7818862003f81565b9050620044d8602083018762004007565b8181036040830152620044ec818662003d69565b9050620044fd606083018562004007565b81810360808301526200416a818462003d69565b602081016200402d828462004007565b6060810162004531828662004007565b818103602083015262004545818562003d69565b9050620036b4604083018462004007565b6080810162004566828762004007565b81810360208301526200457a818662003d69565b90506200458b604083018562004007565b8181036060830152620040ea818462003d69565b602081016200402d828462004012565b60405181810167ffffffffffffffff81118282101715620045cf57600080fd5b604052919050565b600067ffffffffffffffff821115620045ef57600080fd5b5060209081020190565b600067ffffffffffffffff8211156200461157600080fd5b506020601f91909101601f19160190565b60200190565b5190565b600160a060020a031690565b151590565b60ff1690565b82818337506000910152565b60005b838110156200466c57818101518382015260200162004652565b838111156200467c576000848401525b50505050565b601f01601f1916905600608060405234801561001057600080fd5b50604051620010743803806200107483398101604090815281516020808401519284015160068054600160a060020a031916331790559184018051909493909301926100629160009190860190610093565b508151610076906001906020850190610093565b506002805460ff191660ff929092169190911790555061012e9050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d457805160ff1916838001178555610101565b82800160010185558215610101579182015b828111156101015782518255916020019190600101906100e6565b5061010d929150610111565b5090565b61012b91905b8082111561010d5760008155600101610117565b90565b610f36806200013e6000396000f3006080604052600436106100fb5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610100578063095ea7b31461018a57806318160ddd146101c257806323b872dd146101e9578063313ce5671461021357806340c10f191461023e5780634fb2e45d1461026457806370a0823114610285578063715018a6146102a657806379ba5097146102bb5780638da5cb5b146102d057806395d89b41146103015780639dc29fac14610316578063a6f9dae11461033a578063a9059cbb1461035b578063d4ee1d901461037f578063dd62ed3e14610394578063f4c84d19146103bb575b600080fd5b34801561010c57600080fd5b506101156103e7565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561014f578181015183820152602001610137565b50505050905090810190601f16801561017c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561019657600080fd5b506101ae600160a060020a0360043516602435610475565b604080519115158252519081900360200190f35b3480156101ce57600080fd5b506101d76105be565b60408051918252519081900360200190f35b3480156101f557600080fd5b506101ae600160a060020a03600435811690602435166044356105c4565b34801561021f57600080fd5b50610228610716565b6040805160ff9092168252519081900360200190f35b34801561024a57600080fd5b50610262600160a060020a036004351660243561071f565b005b34801561027057600080fd5b50610262600160a060020a0360043516610854565b34801561029157600080fd5b506101d7600160a060020a036004351661096d565b3480156102b257600080fd5b50610262610988565b3480156102c757600080fd5b506102626109f7565b3480156102dc57600080fd5b506102e5610a3c565b60408051600160a060020a039092168252519081900360200190f35b34801561030d57600080fd5b50610115610a4b565b34801561032257600080fd5b50610262600160a060020a0360043516602435610aa5565b34801561034657600080fd5b50610262600160a060020a0360043516610bda565b34801561036757600080fd5b506101ae600160a060020a0360043516602435610c59565b34801561038b57600080fd5b506102e5610d55565b3480156103a057600080fd5b506101d7600160a060020a0360043581169060243516610d64565b3480156103c757600080fd5b506102626024600480358281019290820135918135918201910135610d8f565b6000805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561046d5780601f106104425761010080835404028352916020019161046d565b820191906000526020600020905b81548152906001019060200180831161045057829003601f168201915b505050505081565b6000604060443610156104d2576040805160e560020a62461bcd02815260206004820152601960248201527f5061796c6f61642073697a6520697320696e636f727265637400000000000000604482015290519081900360640190fd5b8215806105005750336000908152600460209081526040808320600160a060020a0388168452909152902054155b1515610556576040805160e560020a62461bcd02815260206004820152600d60248201527f4e6f74207065726d697474656400000000000000000000000000000000000000604482015290519081900360640190fd5b336000818152600460209081526040808320600160a060020a03891680855290835292819020879055805187815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60055481565b600060606064361015610621576040805160e560020a62461bcd02815260206004820152601960248201527f5061796c6f61642073697a6520697320696e636f727265637400000000000000604482015290519081900360640190fd5b600160a060020a03841660009081526003602052604090205461064a908463ffffffff610dff16565b600160a060020a03808616600090815260036020526040808220939093559087168152205461067f908463ffffffff610e1816565b600160a060020a03861660009081526003602090815260408083209390935560048152828220338352905220546106bc908463ffffffff610e1816565b600160a060020a0380871660008181526004602090815260408083203384528252918290209490945580518781529051928816939192600080516020610eeb833981519152929181900390910190a3506001949350505050565b60025460ff1681565b600654600160a060020a0316331461076f576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b80600081116107c8576040805160e560020a62461bcd02815260206004820152600d60248201527f56616c7565206973206e756c6c00000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0383166000908152600360205260409020546107f1908363ffffffff610dff16565b600160a060020a03841660009081526003602052604090205560055461081d908363ffffffff610dff16565b600555604080518381529051600160a060020a03851691600091600080516020610eeb8339815191529181900360200190a3505050565b600654600160a060020a031633146108a4576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b600160a060020a0381161515610904576040805160e560020a62461bcd02815260206004820152601d60248201527f4e6577206f776e657220697320746865207a65726f2061646472657373000000604482015290519081900360640190fd5b600654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600160a060020a031660009081526003602052604090205490565b600654600160a060020a031633146109d8576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b6006805473ffffffffffffffffffffffffffffffffffffffff19169055565b600754600160a060020a0316331415610a3a576007546006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555b565b600654600160a060020a031681565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561046d5780601f106104425761010080835404028352916020019161046d565b600654600160a060020a03163314610af5576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b8060008111610b4e576040805160e560020a62461bcd02815260206004820152600d60248201527f56616c7565206973206e756c6c00000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038316600090815260036020526040902054610b77908363ffffffff610e1816565b600160a060020a038416600090815260036020526040902055600554610ba3908363ffffffff610e1816565b600555604080518381529051600091600160a060020a03861691600080516020610eeb8339815191529181900360200190a3505050565b600654600160a060020a03163314610c2a576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600060406044361015610cb6576040805160e560020a62461bcd02815260206004820152601960248201527f5061796c6f61642073697a6520697320696e636f727265637400000000000000604482015290519081900360640190fd5b33600090815260036020526040902054610cd6908463ffffffff610e1816565b3360009081526003602052604080822092909255600160a060020a03861681522054610d08908463ffffffff610dff16565b600160a060020a038516600081815260036020908152604091829020939093558051868152905191923392600080516020610eeb8339815191529281900390910190a35060019392505050565b600754600160a060020a031681565b600160a060020a03918216600090815260046020908152604080832093909416825291909152205490565b600654600160a060020a03163314610ddf576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b610deb60008585610e2f565b50610df860018383610e2f565b5050505050565b600082820183811015610e1157600080fd5b9392505050565b60008083831115610e2857600080fd5b5050900390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e705782800160ff19823516178555610e9d565b82800160010185558215610e9d579182015b82811115610e9d578235825591602001919060010190610e82565b50610ea9929150610ead565b5090565b610ec791905b80821115610ea95760008155600101610eb3565b9056004e6f74206f776e65720000000000000000000000000000000000000000000000ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a723058206d4252b7c832609eb582477b493727af6d5a697d8bd98ecb4fde197c9b29746b0029a265627a7a72305820eb2ddf721fe7086bedc02025ca331dcf40dabd4ca948de05f9dca0890c181b086c6578706572696d656e74616cf50037
Deployed ByteCode
0x608060405260043610620001d95763ffffffff60e060020a6000350416631785f53c8114620002395780632859c58014620002605780632b56590514620002855780633416794d14620002aa5780633ad8873a14620002cf5780633cc281df146200030e578063408e743d146200033357806341246e5314620003585780634f600ae8146200037d5780634fb2e45d14620003a2578063563cb1ab14620003c7578063570ca735146200040457806358a007fb146200042b5780635c60da1b146200045f5780635d2e9ead14620004775780636bec32da14620004af5780636c45e2dc14620004d45780637048027514620004f9578063715018a6146200051e57806375d2e27d146200053657806379ba5097146200056a5780638c7a63ae14620005825780638da5cb5b14620005b95780639027e6f714620005d15780639947f9321462000609578063a6f9dae1146200062e578063af33f17e1462000653578063b3ab15fb1462000678578063b9073276146200069d578063cbfbd61a14620006d4578063d0ad718d14620006f9578063d4ee1d901462000711578063d51dddd71462000729578063e101d3c1146200075d578063e24e4fdb1462000792578063f3bdd86314620007aa578063f4debe1e14620007cf575b600b54600160a060020a0316801515620002135760405160e560020a62461bcd0281526004016200020a9062004436565b60405180910390fd5b60405136600082376000803683855af43d806000843e81801562000235578184f35b8184fd5b3480156200024657600080fd5b506200025e6200025836600462003693565b620007f4565b005b3480156200026d57600080fd5b506200025e6200027f3660046200393f565b62000881565b3480156200029257600080fd5b506200025e620002a43660046200391e565b620009be565b348015620002b757600080fd5b506200025e620002c9366004620036fb565b62000b66565b348015620002dc57600080fd5b50620002f4620002ee3660046200391e565b62000c1f565b604051620003059392919062004521565b60405180910390f35b3480156200031b57600080fd5b506200025e6200032d36600462003693565b62000ce0565b3480156200034057600080fd5b506200025e62000352366004620036bc565b62000d34565b3480156200036557600080fd5b506200025e62000377366004620036bc565b62000de3565b3480156200038a57600080fd5b506200025e6200039c36600462003ac3565b62000e5a565b348015620003af57600080fd5b506200025e620003c136600462003693565b62001046565b348015620003d457600080fd5b50620003ec620003e636600462003b69565b6200110d565b604051620003059a999897969594939291906200422c565b3480156200041157600080fd5b506200041c620018f7565b6040516200030591906200401d565b3480156200043857600080fd5b50620004506200044a3660046200391e565b62001906565b60405162000305919062004511565b3480156200046c57600080fd5b506200041c62001918565b3480156200048457600080fd5b506200049c620004963660046200391e565b62001928565b60405162000305959493929190620044b4565b348015620004bc57600080fd5b506200025e620004ce366004620036fb565b62001c68565b348015620004e157600080fd5b506200025e620004f336600462003ac3565b62001ce8565b3480156200050657600080fd5b506200025e6200051836600462003693565b62001e8a565b3480156200052b57600080fd5b506200025e62001f0f565b3480156200054357600080fd5b506200055b620005553660046200391e565b62001f5e565b6040516200030591906200459f565b3480156200057757600080fd5b506200025e62001f73565b3480156200058f57600080fd5b50620005a7620005a13660046200391e565b62001fb9565b604051620003059493929190620041c2565b348015620005c657600080fd5b506200041c62002239565b348015620005de57600080fd5b50620005f6620005f03660046200391e565b62002248565b6040516200030595949392919062004328565b3480156200061657600080fd5b506200025e62000628366004620039e4565b62002462565b3480156200063b57600080fd5b506200025e6200064d36600462003693565b6200257f565b3480156200066057600080fd5b506200025e620006723660046200374f565b620025de565b3480156200068557600080fd5b506200025e6200069736600462003693565b620026d7565b348015620006aa57600080fd5b50620006c2620006bc3660046200391e565b62002770565b60405162000305949392919062004556565b348015620006e157600080fd5b506200025e620006f3366004620037df565b620028d1565b3480156200070657600080fd5b5062000450620029f4565b3480156200071e57600080fd5b506200041c620029fa565b3480156200073657600080fd5b506200074e6200074836600462003693565b62002a09565b60405162000305919062004318565b3480156200076a57600080fd5b50620007826200077c3660046200391e565b62002a1e565b60405162000305929190620043ee565b3480156200079f57600080fd5b50620003ec62002ae1565b348015620007b757600080fd5b506200025e620007c936600462003856565b620031d3565b348015620007dc57600080fd5b5062000450620007ee3660046200391e565b62003290565b600854600160a060020a03163314620008245760405160e560020a62461bcd0281526004016200020a906200446c565b600160a060020a0381166000908152600a602052604090819020805460ff19169055517f753f40ca3312b2408759a67875b367955e7baa221daf08aa3d643d96202ac12b90620008769083906200401d565b60405180910390a150565b336000908152600a602052604090205460ff161515620008b85760405160e560020a62461bcd0281526004016200020a9062004490565b600185141562000945576040517fb2dc5dc3000000000000000000000000000000000000000000000000000000008152600160a060020a0385169063b2dc5dc3906200090b908690869060040162004033565b600060405180830381600087803b1580156200092657600080fd5b505af11580156200093b573d6000803e3d6000fd5b50505050620009b7565b60028514156200099a576040517f6b20c454000000000000000000000000000000000000000000000000000000008152600160a060020a03851690636b20c454906200090b9086908690869060040162004057565b60405160e560020a62461bcd0281526004016200020a906200447e565b5050505050565b600854600090600160a060020a03163314620009f15760405160e560020a62461bcd0281526004016200020a906200446c565b60008281526006602052604081206005015483911062000a285760405160e560020a62461bcd0281526004016200020a906200445a565b600091505b60055482101562000b615760008281526007602052604090205483141562000b555760055460001901821462000a7b5760055460001901600090815260076020526040808220548483529120555b60058054600019908101600090815260076020908152604080832083905584549093019093558581526006909252812090818162000aba8282620032c6565b62000aca600183016000620032c6565b62000ada600283016000620032c6565b5060038101805460ff19169055600060049091018190556005830181905562000b08906006840190620032c6565b600782016000905560088201600062000b229190620032c6565b505060405183907fa219112a711e6173c2e8978836823d4e86832d96c0ea2fd05ec77687b7a073ab90600090a262000b61565b60019091019062000a2d565b505050565b336000908152600a602052604090205460ff16151562000b9d5760405160e560020a62461bcd0281526004016200020a9062004490565b6040517f9dc29fac000000000000000000000000000000000000000000000000000000008152600160a060020a03841690639dc29fac9062000be690859085906004016200420d565b600060405180830381600087803b15801562000c0157600080fd5b505af115801562000c16573d6000803e3d6000fd5b50505050505050565b60008181526006602081815260408084206005810154930180548251601f600260001961010060018616150201909316929092049182018590048502810185019093528083529394606094909383018282801562000cc15780601f1062000c955761010080835404028352916020019162000cc1565b820191906000526020600020905b81548152906001019060200180831162000ca357829003601f168201915b5050506000968752505060066020526040909420600701549294915050565b80600160a060020a03166379ba50976040518163ffffffff1660e060020a028152600401600060405180830381600087803b15801562000d1f57600080fd5b505af1158015620009b7573d6000803e3d6000fd5b600854600160a060020a0316331462000d645760405160e560020a62461bcd0281526004016200020a906200446c565b6040517f4fb2e45d000000000000000000000000000000000000000000000000000000008152600160a060020a03831690634fb2e45d9062000dab9084906004016200401d565b600060405180830381600087803b15801562000dc657600080fd5b505af115801562000ddb573d6000803e3d6000fd5b505050505050565b600854600160a060020a0316331462000e135760405160e560020a62461bcd0281526004016200020a906200446c565b6040517fa6f9dae1000000000000000000000000000000000000000000000000000000008152600160a060020a0383169063a6f9dae19062000dab9084906004016200401d565b600854600160a060020a0316331462000e8a5760405160e560020a62461bcd0281526004016200020a906200446c565b60008681526006602052604090206005015486901562000ec15760405160e560020a62461bcd0281526004016200020a9062004424565b600087815260066020818152604090922060058101889055865162000eef9391909201919087019062003311565b50600087815260066020908152604090912060078101859055835162000f1e9260089092019185019062003311565b5085516000888152600660209081526040909120825162000f459391929091019062003311565b5060208087015160008981526006835260409020815162000f70936001909201929091019062003311565b50604080870151600089815260066020908152929020815162000f9e93600290920192919091019062003311565b506060860151600088815260066020908152604080832060038101805460ff191660ff9096169590951790945560808a015160049094019390935560058054835260079091529190208890555462000ff8906001620032a5565b60055560405187907f226f08da880957e11c8affd4d622bb21b058cf67830d2ee56bb82d9b7197e9a7906200103590889088908890889062004556565b60405180910390a250505050505050565b600854600160a060020a03163314620010765760405160e560020a62461bcd0281526004016200020a906200446c565b600160a060020a0381161515620010a45760405160e560020a62461bcd0281526004016200020a9062004448565b600854604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b606080606080606080606080606080600080600060606000935060009250600091506005546040519080825280602002602001820160405280156200115c578160200160208202803883390190505b5090505b6005548310156200122757600760008481526020019081526020016000205491508f6006600084815260200190815260200160002060050154148015620011b757506000828152600660205260409020600701548f145b80620011f457508f6006600084815260200190815260200160002060070154148015620011f457506000828152600660205260409020600501548f145b156200121b578181858151811015156200120a57fe5b602090810290910101526001909301925b60019092019162001160565b8360405190808252806020026020018201604052801562001252578160200160208202803883390190505b509d508360405190808252806020026020018201604052801562001280578160200160208202803883390190505b509c5083604051908082528060200260200182016040528015620012b957816020015b6060815260200190600190039081620012a35790505b509b5083604051908082528060200260200182016040528015620012e7578160200160208202803883390190505b509a50836040519080825280602002602001820160405280156200132057816020015b60608152602001906001900390816200130a5790505b509950836040519080825280602002602001820160405280156200135957816020015b6060815260200190600190039081620013435790505b5098508360405190808252806020026020018201604052801562001387578160200160208202803883390190505b50975083604051908082528060200260200182016040528015620013c057816020015b6060815260200190600190039081620013aa5790505b50965083604051908082528060200260200182016040528015620013f957816020015b6060815260200190600190039081620013e35790505b5095508360405190808252806020026020018201604052801562001427578160200160208202803883390190505b509450600092505b83831015620018e45780838151811015156200144757fe5b906020019060200201519150818e848151811015156200146357fe5b60209081029091018101919091526000838152600690915260409020600501548d518e90859081106200149257fe5b60209081029190910181019190915260008381526006808352604091829020018054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015620015385780601f106200150c5761010080835404028352916020019162001538565b820191906000526020600020905b8154815290600101906020018083116200151a57829003601f168201915b50505050508c848151811015156200154c57fe5b60209081029091018101919091526000838152600690915260409020600701548b518c90859081106200157b57fe5b6020908102919091018101919091526000838152600682526040908190206008018054825160026001831615610100026000190190921691909104601f810185900485028201850190935282815292909190830182828015620016225780601f10620015f65761010080835404028352916020019162001622565b820191906000526020600020905b8154815290600101906020018083116200160457829003601f168201915b50505050508a848151811015156200163657fe5b6020908102909101810191909152600083815260068252604090819020600290810180548351601f60001961010060018516150201909216939093049081018590048502830185019093528282529092909190830182828015620016de5780601f10620016b257610100808354040283529160200191620016de565b820191906000526020600020905b815481529060010190602001808311620016c057829003601f168201915b50505050508984815181101515620016f257fe5b6020908102909101810191909152600083815260069091526040902060030154885160ff909116908990859081106200172757fe5b60ff909216602092830290910182015260008381526006825260409081902080548251601f600260001961010060018616150201909316929092049182018590048502810185019093528083529192909190830182828015620017ce5780601f10620017a257610100808354040283529160200191620017ce565b820191906000526020600020905b815481529060010190602001808311620017b057829003601f168201915b50505050508784815181101515620017e257fe5b602090810291909101810191909152600083815260068252604090819020600190810180548351600293821615610100026000190190911692909204601f810185900485028301850190935282825290929091908301828280156200188b5780601f106200185f576101008083540402835291602001916200188b565b820191906000526020600020905b8154815290600101906020018083116200186d57829003601f168201915b505050505086848151811015156200189f57fe5b60209081029091018101919091526000838152600690915260409020600401548551869085908110620018ce57fe5b602090810290910101526001909201916200142f565b505050509295989b9194979a5092959850565b600c54600160a060020a031681565b60076020526000908152604090205481565b600b54600160a060020a03165b90565b6006602090815260009182526040918290208251815460026001821615610100026000190190911604601f8101849004909302810160c090810190945260a08101838152919390928492849290918491840182828015620019cd5780601f10620019a157610100808354040283529160200191620019cd565b820191906000526020600020905b815481529060010190602001808311620019af57829003601f168201915b50505050508152602001600182018054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801562001a735780601f1062001a475761010080835404028352916020019162001a73565b820191906000526020600020905b81548152906001019060200180831162001a5557829003601f168201915b5050509183525050600282810180546040805160206001841615610100026000190190931694909404601f8101839004830285018301909152808452938101939083018282801562001b095780601f1062001add5761010080835404028352916020019162001b09565b820191906000526020600020905b81548152906001019060200180831162001aeb57829003601f168201915b5050509183525050600382015460ff1660208083019190915260049092015460409182015260058401546006850180548351601f6002600019600185161561010002019093169290920491820186900486028101860190945280845294959194919390919083018282801562001bc35780601f1062001b975761010080835404028352916020019162001bc3565b820191906000526020600020905b81548152906001019060200180831162001ba557829003601f168201915b50505050600783015460088401805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152959693959394509083018282801562001c5e5780601f1062001c325761010080835404028352916020019162001c5e565b820191906000526020600020905b81548152906001019060200180831162001c4057829003601f168201915b5050505050905085565b336000908152600a602052604090205460ff16151562001c9f5760405160e560020a62461bcd0281526004016200020a9062004490565b6040517f40c10f19000000000000000000000000000000000000000000000000000000008152600160a060020a038416906340c10f199062000be690859085906004016200420d565b600854600160a060020a0316331462001d185760405160e560020a62461bcd0281526004016200020a906200446c565b60008681526006602052604081206005015487911062001d4f5760405160e560020a62461bcd0281526004016200020a906200445a565b85516000888152600660209081526040909120825162001d759391929091019062003311565b5060208087015160008981526006835260409020815162001da0936001909201929091019062003311565b50604080870151600089815260066020908152929020815162001dce93600290920192919091019062003311565b506060860151600088815260066020818152604090922060038101805460ff191660ff909516949094179093556080890151600484015560058301889055865162001e20939091019187019062003311565b50600087815260066020908152604090912060078101859055835162001e4f9260089092019185019062003311565b50867f4eb0f9fb05e08613a2eba9dc272a43421cf32f9ccab592725ab663e3238f5f55878787878760405162001035959493929190620044b4565b600854600160a060020a0316331462001eba5760405160e560020a62461bcd0281526004016200020a906200446c565b600160a060020a0381166000908152600a602052604090819020805460ff19166001179055517fad6de4452a631e641cb59902236607946ce9272b9b981f2f80e8d129cb9084ba90620008769083906200401d565b600854600160a060020a0316331462001f3f5760405160e560020a62461bcd0281526004016200020a906200446c565b6008805473ffffffffffffffffffffffffffffffffffffffff19169055565b600d6020526000908152604090205460ff1681565b600954600160a060020a031633141562001fb7576009546008805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555b565b600081815260066020526040812060050154606090819083908190151562002006576040805160208181018352600080835283519182019093528281529196509450925084915062002231565b60008681526006602090815260409182902060080180548351601f60026000196101006001861615020190931692909204918201849004840281018401909452808452620020af9392830182828015620020a45780601f106200207857610100808354040283529160200191620020a4565b820191906000526020600020905b8154815290600101906020018083116200208657829003601f168201915b5050505050620032bf565b905080600160a060020a03166306fdde036040518163ffffffff1660e060020a028152600401600060405180830381600087803b158015620020f057600080fd5b505af115801562002105573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200212f9190810190620038e5565b935080600160a060020a03166395d89b416040518163ffffffff1660e060020a028152600401600060405180830381600087803b1580156200217057600080fd5b505af115801562002185573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620021af9190810190620038e5565b925080600160a060020a031663313ce5676040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015620021f057600080fd5b505af115801562002205573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506200222b919081019062003b9e565b91508094505b509193509193565b600854600160a060020a031681565b600081815260066020908152604080832080548251601f6002600019610100600186161502019093169290920491820185900485028101850190935280835260609485948594919384939091830182828015620022e95780601f10620022bd57610100808354040283529160200191620022e9565b820191906000526020600020905b815481529060010190602001808311620022cb57829003601f168201915b505050600089815260066020908152604091829020600190810180548451600293821615610100026000190190911692909204601f8101849004840283018401909452838252959a509493509091508301828280156200238d5780601f1062002361576101008083540402835291602001916200238d565b820191906000526020600020905b8154815290600101906020018083116200236f57829003601f168201915b5050506000898152600660209081526040918290206002908101805484516001821615610100026000190190911692909204601f8101849004840283018401909452838252959950949350909150830182828015620024305780601f10620024045761010080835404028352916020019162002430565b820191906000526020600020905b8154815290600101906020018083116200241257829003601f168201915b50505060009889525050600660205260409096206003810154600490910154959794969560ff90911694909350915050565b336000908152600a602052604090205460ff161515620024995760405160e560020a62461bcd0281526004016200020a9062004490565b600186141562002528576040517f22862482000000000000000000000000000000000000000000000000000000008152600160a060020a03861690632286248290620024ee90879087908690600401620040f4565b600060405180830381600087803b1580156200250957600080fd5b505af11580156200251e573d6000803e3d6000fd5b5050505062000ddb565b60028614156200099a576040517f1f7fdffa000000000000000000000000000000000000000000000000000000008152600160a060020a03861690631f7fdffa90620024ee9087908790879087906004016200409a565b600854600160a060020a03163314620025af5760405160e560020a62461bcd0281526004016200020a906200446c565b6009805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600854600160a060020a031633146200260e5760405160e560020a62461bcd0281526004016200020a906200446c565b6040517ff4c84d19000000000000000000000000000000000000000000000000000000008152600160a060020a0386169063f4c84d19906200265b90879087908790879060040162004387565b600060405180830381600087803b1580156200267657600080fd5b505af11580156200268b573d6000803e3d6000fd5b505050507f86ead451719b8f4b763de2648808971e9bf540eed93efadafb044cd7ef5d91f48585858585604051620026c89594939291906200412e565b60405180910390a15050505050565b600854600160a060020a03163314620027075760405160e560020a62461bcd0281526004016200020a906200446c565b600c54604051600160a060020a038084169216907f2709918445f306d3e94d280907c62c5d2525ac3192d2e544774c7f181d65af3e90600090a3600c805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b60008181526006602081815260408084206005810154930180548251601f60026000196101006001861615020190931692909204918201859004850281018501909352808352939460609490938593929190830182828015620028175780601f10620027eb5761010080835404028352916020019162002817565b820191906000526020600020905b815481529060010190602001808311620027f957829003601f168201915b505050600088815260066020908152604091829020600781015460089091018054845160026001831615610100026000190190921691909104601f81018590048502820185019095528481529699509097509350909150830182828015620028c35780601f106200289757610100808354040283529160200191620028c3565b820191906000526020600020905b815481529060010190602001808311620028a557829003601f168201915b505050505090509193509193565b600c54600090600160a060020a03163314620029045760405160e560020a62461bcd0281526004016200020a90620044a2565b838214620029295760405160e560020a62461bcd0281526004016200020a9062004412565b5060005b83811015620009b7578282828181106200294357fe5b9050602002013560ff16600d600087878581811015156200296057fe5b90506020020135815260200190815260200160002060006101000a81548160ff021916908360ff16021790555082828281811015156200299c57fe5b9050602002013560ff1660ff168585838181101515620029b857fe5b905060200201357f20f86c53e8884644ce473603799d40ecf47d8c4c1d55384fe8d0eeaf697786eb60405160405180910390a36001016200292d565b60055481565b600954600160a060020a031681565b600a6020526000908152604090205460ff1681565b60008181526006602090815260408083206002908101805483516001821615610100026000190190911692909204601f8101859004850283018501909352828252606094939192909183018282801562002abc5780601f1062002a905761010080835404028352916020019162002abc565b820191906000526020600020905b81548152906001019060200180831162002a9e57829003601f168201915b505050600095865250506006602052604090932060030154929360ff90931692915050565b606080606080606080606080606080600080600080600554935060009250600091508360405190808252806020026020018201604052801562002b2e578160200160208202803883390190505b509d508360405190808252806020026020018201604052801562002b5c578160200160208202803883390190505b509c508360405190808252806020026020018201604052801562002b9557816020015b606081526020019060019003908162002b7f5790505b509b508360405190808252806020026020018201604052801562002bc3578160200160208202803883390190505b509a508360405190808252806020026020018201604052801562002bfc57816020015b606081526020019060019003908162002be65790505b5099508360405190808252806020026020018201604052801562002c3557816020015b606081526020019060019003908162002c1f5790505b5098508360405190808252806020026020018201604052801562002c63578160200160208202803883390190505b5097508360405190808252806020026020018201604052801562002c9c57816020015b606081526020019060019003908162002c865790505b5096508360405190808252806020026020018201604052801562002cd557816020015b606081526020019060019003908162002cbf5790505b5095508360405190808252806020026020018201604052801562002d03578160200160208202803883390190505b5094506000915060009250600090505b600554811015620031c3576000818152600760205260409020548e5190935083908f908490811062002d4157fe5b60209081029091018101919091526000848152600690915260409020600501548d518e908490811062002d7057fe5b60209081029190910181019190915260008481526006808352604091829020018054825160026001831615610100026000190190921691909104601f81018590048502820185019093528281529290919083018282801562002e165780601f1062002dea5761010080835404028352916020019162002e16565b820191906000526020600020905b81548152906001019060200180831162002df857829003601f168201915b50505050508c8381518110151562002e2a57fe5b60209081029091018101919091526000848152600690915260409020600701548b518c908490811062002e5957fe5b6020908102919091018101919091526000848152600682526040908190206008018054825160026001831615610100026000190190921691909104601f81018590048502820185019093528281529290919083018282801562002f005780601f1062002ed45761010080835404028352916020019162002f00565b820191906000526020600020905b81548152906001019060200180831162002ee257829003601f168201915b50505050508a8381518110151562002f1457fe5b6020908102909101810191909152600084815260068252604090819020600290810180548351601f6000196101006001851615020190921693909304908101859004850283018501909352828252909290919083018282801562002fbc5780601f1062002f905761010080835404028352916020019162002fbc565b820191906000526020600020905b81548152906001019060200180831162002f9e57829003601f168201915b5050505050898381518110151562002fd057fe5b6020908102909101810191909152600084815260069091526040902060030154885160ff909116908990849081106200300557fe5b60ff909216602092830290910182015260008481526006825260409081902080548251601f600260001961010060018616150201909316929092049182018590048502810185019093528083529192909190830182828015620030ac5780601f106200308057610100808354040283529160200191620030ac565b820191906000526020600020905b8154815290600101906020018083116200308e57829003601f168201915b50505050508783815181101515620030c057fe5b602090810291909101810191909152600084815260068252604090819020600190810180548351600293821615610100026000190190911692909204601f81018590048502830185019093528282529092909190830182828015620031695780601f106200313d5761010080835404028352916020019162003169565b820191906000526020600020905b8154815290600101906020018083116200314b57829003601f168201915b505050505086838151811015156200317d57fe5b60209081029091018101919091526000848152600690915260409020600401548551869084908110620031ac57fe5b602090810290910101526001918201910162002d13565b5050505090919293949596979899565b600854600090600160a060020a03163314620032065760405160e560020a62461bcd0281526004016200020a906200446c565b85858585856200321562003396565b62003225959493929190620043b2565b604051809103906000f08015801562003242573d6000803e3d6000fd5b5090507fbb5f9980e27ec75b79e41ce422e643c6c0116fd9f599776a72f89032f70fe205818787878787604051620032809695949392919062004175565b60405180910390a1505050505050565b60009081526006602052604090206004015490565b600082820183811015620032b857600080fd5b9392505050565b6014015190565b50805460018160011615610100020316600290046000825580601f10620032ee57506200330e565b601f0160209004906000526020600020908101906200330e9190620033a7565b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200335457805160ff191683800117855562003384565b8280016001018555821562003384579182015b828111156200338457825182559160200191906001019062003367565b5062003392929150620033a7565b5090565b604051611074806200468d83390190565b6200192591905b80821115620033925760008155600101620033ae565b6000620032b882356200462c565b600080601f83018413620033e557600080fd5b50813567ffffffffffffffff811115620033fe57600080fd5b6020830191508360208202830111156200341757600080fd5b9250929050565b6000601f820183136200343057600080fd5b8135620034476200344182620045d7565b620045af565b915081818352602084019350602081019050838560208402820111156200346d57600080fd5b60005b838110156200349d578162003486888262003669565b845250602092830192919091019060010162003470565b5050505092915050565b6000601f82018313620034b957600080fd5b8135620034ca6200344182620045f9565b91508082526020830160208301858383011115620034e757600080fd5b620034f483828462004643565b50505092915050565b600080601f830184136200351057600080fd5b50813567ffffffffffffffff8111156200352957600080fd5b6020830191508360018202830111156200341757600080fd5b6000601f820183136200355457600080fd5b8151620035656200344182620045f9565b915080825260208301602083018583830111156200358257600080fd5b620034f48382846200464f565b600060a08284031215620035a257600080fd5b620035ae60a0620045af565b9050813567ffffffffffffffff811115620035c857600080fd5b620035d684828501620034a7565b825250602082013567ffffffffffffffff811115620035f457600080fd5b6200360284828501620034a7565b602083015250604082013567ffffffffffffffff8111156200362357600080fd5b6200363184828501620034a7565b6040830152506060620036478482850162003677565b60608301525060806200365d8482850162003669565b60808301525092915050565b6000620032b8823562001925565b6000620032b882356200463d565b6000620032b882516200463d565b600060208284031215620036a657600080fd5b6000620036b48484620033c4565b949350505050565b60008060408385031215620036d057600080fd5b6000620036de8585620033c4565b9250506020620036f185828601620033c4565b9150509250929050565b6000806000606084860312156200371157600080fd5b60006200371f8686620033c4565b93505060206200373286828701620033c4565b9250506040620037458682870162003669565b9150509250925092565b6000806000806000606086880312156200376857600080fd5b6000620037768888620033c4565b955050602086013567ffffffffffffffff8111156200379457600080fd5b620037a288828901620034fd565b9450945050604086013567ffffffffffffffff811115620037c257600080fd5b620037d088828901620034fd565b92509250509295509295909350565b60008060008060408587031215620037f657600080fd5b843567ffffffffffffffff8111156200380e57600080fd5b6200381c87828801620033d2565b9450945050602085013567ffffffffffffffff8111156200383c57600080fd5b6200384a87828801620033d2565b95989497509550505050565b6000806000806000606086880312156200386f57600080fd5b853567ffffffffffffffff8111156200388757600080fd5b6200389588828901620034fd565b9550955050602086013567ffffffffffffffff811115620038b557600080fd5b620038c388828901620034fd565b93509350506040620038d88882890162003677565b9150509295509295909350565b600060208284031215620038f857600080fd5b815167ffffffffffffffff8111156200391057600080fd5b620036b48482850162003542565b6000602082840312156200393157600080fd5b6000620036b4848462003669565b600080600080600060a086880312156200395857600080fd5b600062003966888862003669565b95505060206200397988828901620033c4565b94505060406200398c88828901620033c4565b935050606086013567ffffffffffffffff811115620039aa57600080fd5b620039b8888289016200341e565b925050608086013567ffffffffffffffff811115620039d657600080fd5b620038d8888289016200341e565b60008060008060008060c08789031215620039fe57600080fd5b600062003a0c898962003669565b965050602062003a1f89828a01620033c4565b955050604062003a3289828a01620033c4565b945050606087013567ffffffffffffffff81111562003a5057600080fd5b62003a5e89828a016200341e565b935050608087013567ffffffffffffffff81111562003a7c57600080fd5b62003a8a89828a016200341e565b92505060a087013567ffffffffffffffff81111562003aa857600080fd5b62003ab689828a01620034a7565b9150509295509295509295565b60008060008060008060c0878903121562003add57600080fd5b600062003aeb898962003669565b965050602087013567ffffffffffffffff81111562003b0957600080fd5b62003b1789828a016200358f565b955050604062003b2a89828a0162003669565b945050606087013567ffffffffffffffff81111562003b4857600080fd5b62003b5689828a01620034a7565b935050608062003a8a89828a0162003669565b6000806040838503121562003b7d57600080fd5b600062003b8b858562003669565b9250506020620036f18582860162003669565b60006020828403121562003bb157600080fd5b6000620036b4848462003685565b62003bca816200462c565b82525050565b600062003bdd8262004628565b8084526020840193508360208202850162003bf88562004622565b60005b8481101562003c3557838303885262003c1683835162003d69565b925062003c238262004622565b60209890980197915060010162003bfb565b50909695505050505050565b600062003c4e8262004628565b8084526020840193508360208202850162003c698562004622565b60005b8481101562003c3557838303885262003c8783835162003d69565b925062003c948262004622565b60209890980197915060010162003c6c565b600062003cb38262004628565b80845260208401935062003cc78362004622565b60005b8281101562003cfd5762003ce086835162004007565b62003ceb8262004622565b60209690960195915060010162003cca565b5093949350505050565b600062003d148262004628565b80845260208401935062003d288362004622565b60005b8281101562003cfd5762003d4186835162004012565b62003d4c8262004622565b60209690960195915060010162003d2b565b62003bca8162004638565b600062003d768262004628565b80845262003d8c8160208601602086016200464f565b62003d978162004682565b9093016020019392505050565b600082845260208401935062003dbc83858462004643565b62003dc78362004682565b9093019392505050565b600f81527f6c656e677468206d69736d617463680000000000000000000000000000000000602082015260400190565b600b81527f746f6b656e206578697374000000000000000000000000000000000000000000602082015260400190565b601f81527f696d706c656d656e746174696f6e20636f6e7472616374206e6f742073657400602082015260400190565b601d81527f4e6577206f776e657220697320746865207a65726f2061646472657373000000602082015260400190565b600f81527f746f6b656e206e6f742065786973740000000000000000000000000000000000602082015260400190565b600981527f4e6f74206f776e65720000000000000000000000000000000000000000000000602082015260400190565b601081527f496e76616c6964204e4654207479706500000000000000000000000000000000602082015260400190565b600981527f6e6f742061646d696e0000000000000000000000000000000000000000000000602082015260400190565b600c81527f6e6f74206f70657261746f720000000000000000000000000000000000000000602082015260400190565b805160a08084526000919084019062003f9b828262003d69565b9150506020830151848203602086015262003fb7828262003d69565b9150506040830151848203604086015262003fd3828262003d69565b915050606083015162003fea606086018262004012565b50608083015162003fff608086018262004007565b509392505050565b62003bca8162001925565b62003bca816200463d565b602081016200402d828462003bbf565b92915050565b6040810162004043828562003bbf565b8181036020830152620036b4818462003ca6565b6060810162004067828662003bbf565b81810360208301526200407b818562003ca6565b9050818103604083015262004091818462003ca6565b95945050505050565b60808101620040aa828762003bbf565b8181036020830152620040be818662003ca6565b90508181036040830152620040d4818562003ca6565b90508181036060830152620040ea818462003d69565b9695505050505050565b6060810162004104828662003bbf565b818103602083015262004118818562003ca6565b9050818103604083015262004091818462003d69565b606081016200413e828862003bbf565b81810360208301526200415381868862003da4565b905081810360408301526200416a81848662003da4565b979650505050505050565b6080810162004185828962003bbf565b81810360208301526200419a81878962003da4565b90508181036040830152620041b181858762003da4565b90506200416a606083018462004012565b60808101620041d2828762003bbf565b8181036020830152620041e6818662003d69565b90508181036040830152620041fc818562003d69565b905062004091606083018462004012565b604081016200421d828562003bbf565b620032b8602083018462004007565b610140808252810162004240818d62003ca6565b9050818103602083015262004256818c62003ca6565b905081810360408301526200426c818b62003bd0565b9050818103606083015262004282818a62003ca6565b9050818103608083015262004298818962003bd0565b905081810360a0830152620042ae818862003c41565b905081810360c0830152620042c4818762003d07565b905081810360e0830152620042da818662003bd0565b9050818103610100830152620042f1818562003c41565b905081810361012083015262004308818462003ca6565b9c9b505050505050505050505050565b602081016200402d828462003d5e565b60a080825281016200433b818862003d69565b9050818103602083015262004351818762003d69565b9050818103604083015262004367818662003d69565b905062004378606083018562004012565b620040ea608083018462004007565b604080825281016200439b81868862003da4565b90508181036020830152620040ea81848662003da4565b60608082528101620043c681878962003da4565b90508181036020830152620043dd81858762003da4565b9050620040ea604083018462004012565b6040808252810162004401818562003d69565b9050620032b8602083018462004012565b602080825281016200402d8162003dd1565b602080825281016200402d8162003e01565b602080825281016200402d8162003e31565b602080825281016200402d8162003e61565b602080825281016200402d8162003e91565b602080825281016200402d8162003ec1565b602080825281016200402d8162003ef1565b602080825281016200402d8162003f21565b602080825281016200402d8162003f51565b60a08082528101620044c7818862003f81565b9050620044d8602083018762004007565b8181036040830152620044ec818662003d69565b9050620044fd606083018562004007565b81810360808301526200416a818462003d69565b602081016200402d828462004007565b6060810162004531828662004007565b818103602083015262004545818562003d69565b9050620036b4604083018462004007565b6080810162004566828762004007565b81810360208301526200457a818662003d69565b90506200458b604083018562004007565b8181036060830152620040ea818462003d69565b602081016200402d828462004012565b60405181810167ffffffffffffffff81118282101715620045cf57600080fd5b604052919050565b600067ffffffffffffffff821115620045ef57600080fd5b5060209081020190565b600067ffffffffffffffff8211156200461157600080fd5b506020601f91909101601f19160190565b60200190565b5190565b600160a060020a031690565b151590565b60ff1690565b82818337506000910152565b60005b838110156200466c57818101518382015260200162004652565b838111156200467c576000848401525b50505050565b601f01601f1916905600608060405234801561001057600080fd5b50604051620010743803806200107483398101604090815281516020808401519284015160068054600160a060020a031916331790559184018051909493909301926100629160009190860190610093565b508151610076906001906020850190610093565b506002805460ff191660ff929092169190911790555061012e9050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d457805160ff1916838001178555610101565b82800160010185558215610101579182015b828111156101015782518255916020019190600101906100e6565b5061010d929150610111565b5090565b61012b91905b8082111561010d5760008155600101610117565b90565b610f36806200013e6000396000f3006080604052600436106100fb5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde038114610100578063095ea7b31461018a57806318160ddd146101c257806323b872dd146101e9578063313ce5671461021357806340c10f191461023e5780634fb2e45d1461026457806370a0823114610285578063715018a6146102a657806379ba5097146102bb5780638da5cb5b146102d057806395d89b41146103015780639dc29fac14610316578063a6f9dae11461033a578063a9059cbb1461035b578063d4ee1d901461037f578063dd62ed3e14610394578063f4c84d19146103bb575b600080fd5b34801561010c57600080fd5b506101156103e7565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561014f578181015183820152602001610137565b50505050905090810190601f16801561017c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561019657600080fd5b506101ae600160a060020a0360043516602435610475565b604080519115158252519081900360200190f35b3480156101ce57600080fd5b506101d76105be565b60408051918252519081900360200190f35b3480156101f557600080fd5b506101ae600160a060020a03600435811690602435166044356105c4565b34801561021f57600080fd5b50610228610716565b6040805160ff9092168252519081900360200190f35b34801561024a57600080fd5b50610262600160a060020a036004351660243561071f565b005b34801561027057600080fd5b50610262600160a060020a0360043516610854565b34801561029157600080fd5b506101d7600160a060020a036004351661096d565b3480156102b257600080fd5b50610262610988565b3480156102c757600080fd5b506102626109f7565b3480156102dc57600080fd5b506102e5610a3c565b60408051600160a060020a039092168252519081900360200190f35b34801561030d57600080fd5b50610115610a4b565b34801561032257600080fd5b50610262600160a060020a0360043516602435610aa5565b34801561034657600080fd5b50610262600160a060020a0360043516610bda565b34801561036757600080fd5b506101ae600160a060020a0360043516602435610c59565b34801561038b57600080fd5b506102e5610d55565b3480156103a057600080fd5b506101d7600160a060020a0360043581169060243516610d64565b3480156103c757600080fd5b506102626024600480358281019290820135918135918201910135610d8f565b6000805460408051602060026001851615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561046d5780601f106104425761010080835404028352916020019161046d565b820191906000526020600020905b81548152906001019060200180831161045057829003601f168201915b505050505081565b6000604060443610156104d2576040805160e560020a62461bcd02815260206004820152601960248201527f5061796c6f61642073697a6520697320696e636f727265637400000000000000604482015290519081900360640190fd5b8215806105005750336000908152600460209081526040808320600160a060020a0388168452909152902054155b1515610556576040805160e560020a62461bcd02815260206004820152600d60248201527f4e6f74207065726d697474656400000000000000000000000000000000000000604482015290519081900360640190fd5b336000818152600460209081526040808320600160a060020a03891680855290835292819020879055805187815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b60055481565b600060606064361015610621576040805160e560020a62461bcd02815260206004820152601960248201527f5061796c6f61642073697a6520697320696e636f727265637400000000000000604482015290519081900360640190fd5b600160a060020a03841660009081526003602052604090205461064a908463ffffffff610dff16565b600160a060020a03808616600090815260036020526040808220939093559087168152205461067f908463ffffffff610e1816565b600160a060020a03861660009081526003602090815260408083209390935560048152828220338352905220546106bc908463ffffffff610e1816565b600160a060020a0380871660008181526004602090815260408083203384528252918290209490945580518781529051928816939192600080516020610eeb833981519152929181900390910190a3506001949350505050565b60025460ff1681565b600654600160a060020a0316331461076f576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b80600081116107c8576040805160e560020a62461bcd02815260206004820152600d60248201527f56616c7565206973206e756c6c00000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a0383166000908152600360205260409020546107f1908363ffffffff610dff16565b600160a060020a03841660009081526003602052604090205560055461081d908363ffffffff610dff16565b600555604080518381529051600160a060020a03851691600091600080516020610eeb8339815191529181900360200190a3505050565b600654600160a060020a031633146108a4576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b600160a060020a0381161515610904576040805160e560020a62461bcd02815260206004820152601d60248201527f4e6577206f776e657220697320746865207a65726f2061646472657373000000604482015290519081900360640190fd5b600654604051600160a060020a038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a36006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600160a060020a031660009081526003602052604090205490565b600654600160a060020a031633146109d8576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b6006805473ffffffffffffffffffffffffffffffffffffffff19169055565b600754600160a060020a0316331415610a3a576007546006805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a039092169190911790555b565b600654600160a060020a031681565b60018054604080516020600284861615610100026000190190941693909304601f8101849004840282018401909252818152929183018282801561046d5780601f106104425761010080835404028352916020019161046d565b600654600160a060020a03163314610af5576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b8060008111610b4e576040805160e560020a62461bcd02815260206004820152600d60248201527f56616c7565206973206e756c6c00000000000000000000000000000000000000604482015290519081900360640190fd5b600160a060020a038316600090815260036020526040902054610b77908363ffffffff610e1816565b600160a060020a038416600090815260036020526040902055600554610ba3908363ffffffff610e1816565b600555604080518381529051600091600160a060020a03861691600080516020610eeb8339815191529181900360200190a3505050565b600654600160a060020a03163314610c2a576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b6007805473ffffffffffffffffffffffffffffffffffffffff1916600160a060020a0392909216919091179055565b600060406044361015610cb6576040805160e560020a62461bcd02815260206004820152601960248201527f5061796c6f61642073697a6520697320696e636f727265637400000000000000604482015290519081900360640190fd5b33600090815260036020526040902054610cd6908463ffffffff610e1816565b3360009081526003602052604080822092909255600160a060020a03861681522054610d08908463ffffffff610dff16565b600160a060020a038516600081815260036020908152604091829020939093558051868152905191923392600080516020610eeb8339815191529281900390910190a35060019392505050565b600754600160a060020a031681565b600160a060020a03918216600090815260046020908152604080832093909416825291909152205490565b600654600160a060020a03163314610ddf576040805160e560020a62461bcd0281526020600482015260096024820152600080516020610ecb833981519152604482015290519081900360640190fd5b610deb60008585610e2f565b50610df860018383610e2f565b5050505050565b600082820183811015610e1157600080fd5b9392505050565b60008083831115610e2857600080fd5b5050900390565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e705782800160ff19823516178555610e9d565b82800160010185558215610e9d579182015b82811115610e9d578235825591602001919060010190610e82565b50610ea9929150610ead565b5090565b610ec791905b80821115610ea95760008155600101610eb3565b9056004e6f74206f776e65720000000000000000000000000000000000000000000000ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa165627a7a723058206d4252b7c832609eb582477b493727af6d5a697d8bd98ecb4fde197c9b29746b0029a265627a7a72305820eb2ddf721fe7086bedc02025ca331dcf40dabd4ca948de05f9dca0890c181b086c6578706572696d656e74616cf50037