-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- DkargoToken: 토큰 컨트랙트, mainnet에서 운용 - DkargoFund: 락업 컨트랙트, mainnet에서 운용 - DkargoService: 디카르고 플랫폼 관리 컨트랙트, privnet에서 운용 - DkargoCompany: 물류사 컨트랙트, privnet에서 운용 - DkargoOrder: 주문 컨트랙트, privnet에서 운용
- Loading branch information
0 parents
commit 292fecb
Showing
28 changed files
with
2,258 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
package-lock.json | ||
build | ||
node_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.6.0 <0.7.0; | ||
|
||
import "./DkargoPrefix.sol"; | ||
import "./authority/Operatorship.sol"; | ||
import "./introspection/ERC165/ERC165.sol"; | ||
import "./libs/Address.sol"; | ||
import "./libs/chain/ChainAddress.sol"; | ||
import "./libs/chain/Typedef.sol"; | ||
|
||
/// @title DkargoCompany | ||
/// @notice 물류사 컨트랙트 정의 | ||
/// @author jhhong | ||
contract DkargoCompany is Operatorship, ERC165, DkargoPrefix { | ||
using Address for address; | ||
using ChainAddress for Typedef.AddressList; | ||
|
||
/// @dev 변수 선언 | ||
string private _name; // 물류사 이름 | ||
string private _url; // 물류사 상세정보 URL | ||
address private _recipient; // 인센티브 수취인 주소 | ||
address private _service; // 서비스 컨트랙트 주소 | ||
mapping(address => mapping(uint256 => bool)) private _todolist; // 접수되어 처리해야 할 주문정보 | ||
Typedef.AddressList private _orderchain; // 주문 체인 (물류사 관할) | ||
|
||
/// @notice 컨트랙트 생성자이다. | ||
/// @param name 물류사 이름 | ||
/// @param url 물류사 상세정보가 저장된 URL (string) | ||
/// @param recipient 인센티브 수취인 주소 | ||
/// @param service 서비스 컨트랙트 주소 | ||
constructor(string memory name, string memory url, address recipient, address service) public { | ||
_setDkargoPrefix("company"); // 프리픽스 설정 | ||
_registerInterface(0x946edbed); // INTERFACE ID 등록 (getDkargoPrefix) | ||
_name = name; | ||
_url = url; | ||
_recipient = recipient; | ||
_service = service; | ||
} | ||
|
||
/// @notice 물류사 등록을 위해 DKA를 staking한다. | ||
/// @param amount staking할 DKA 수량 | ||
function staking(uint256 amount) onlyOwner public { | ||
/* need to design */ | ||
} | ||
|
||
/// @notice DKA를 unstaking한다. | ||
function unstaking() onlyOwner public { | ||
/* need to design */ | ||
} | ||
|
||
/// @notice 주문을 접수한다. | ||
/// @dev 주문접수(todolist 갱신), 주문이 물류사 체인에 없으면 등록 | ||
/// @param order 주문 컨트랙트 주소 | ||
/// @param transportid 운송번호 (구간배송번호) | ||
function launch(address order, uint256 transportid) onlyOperator public { | ||
_todolist[order][transportid] =true; // 주문접수(todolist 갱신) | ||
if(_orderchain.isLinked(order) == false) { | ||
_orderchain.linkChain(order); // 물류사체인에 주문등록 | ||
} | ||
} | ||
|
||
/// @notice 주문 상태코드를 갱신한다. | ||
/// @dev 담당 구간 배송 종료(완료/실패) -> 다음 담당 물류사에게 알람 | ||
/// @param order 주문 컨트랙트 주소 | ||
/// @param transportid 운송번호 (구간배송번호) | ||
/// @param code 배송상태 코드 번호 | ||
function updateOrderCode(address order, uint256 transportid, uint256 code) onlyOperator public { | ||
//// 물류사 관할 주문인지 아닌지 체크 (실수로 launch과정을 생략하였다면 여기서 revert될 것임) | ||
require(_orderchain.isLinked(order) == true, "DkargoCompany: unregistered order"); | ||
require(_todolist[order][transportid] == true, "DkargoCompany: unlaunched order"); | ||
_submitUpdate(order, code); | ||
} | ||
|
||
/// @notice 물류사 이름을 설정한다. | ||
/// @dev onlyOwner | ||
/// @param name 물류사 이름 | ||
function setName(string memory name) onlyOwner public { | ||
_name = name; | ||
} | ||
|
||
/// @notice 물류사 URL을 설정한다. | ||
/// @dev onlyOwner | ||
/// @param url 물류사 URL | ||
function setUrl(string memory url) onlyOwner public { | ||
_url = url; | ||
} | ||
|
||
/// @notice 물류사의 수취인 주소를 설정한다. | ||
/// @dev onlyOwner | ||
/// @param recipient 물류사 수취인 주소 | ||
function setRecipient(address recipient) onlyOwner public { | ||
_recipient = recipient; | ||
} | ||
|
||
/// @notice 물류사에 등록된 첫번째 주문 컨트랙트 주소를 반환한다. | ||
/// @return 주문 컨트랙트 주소 (address) | ||
function firstOrder() public view returns(address) { | ||
return _orderchain.first(); | ||
} | ||
|
||
/// @notice 주문 구간배송이 물류사에 접수되었는지 확인한다. | ||
/// @param order 주문 컨트랙트 주소 | ||
/// @param transportid 운송번호 (구간배송번호) | ||
/// @return 주문 접수여부 (bool) | ||
function isLaunched(address order, uint256 transportid) public view returns(bool) { | ||
return _todolist[order][transportid]; | ||
} | ||
|
||
/// @notice 물류사에 등록된 마지막 주문 컨트랙트 주소를 반환한다. | ||
/// @return 주문 컨트랙트 주소 (address) | ||
function lastOrder() public view returns(address) { | ||
return _orderchain.last(); | ||
} | ||
|
||
/// @notice 물류사 이름을 반환한다. | ||
/// @return 물류사 이름 (string) | ||
function name() public view returns(string memory) { | ||
return _name; | ||
} | ||
|
||
/// @notice 물류사에 등록된 주문 리스트에서 order 바로 다음의 주문 컨트랙트 주소를 반환한다. | ||
/// @param order 주문 컨트랙트 주소 | ||
/// @return order 다음의 주문 컨트랙트 주소 (address) | ||
function nextOrder(address order) public view returns(address) { | ||
return _orderchain.nextOf(order); | ||
} | ||
|
||
/// @notice 물류사에 등록된 마지막 주문 컨트랙트 개수를 반환한다. | ||
/// @return 주문 컨트랙트 개수 (uint256) | ||
function orderCount() public view returns(uint256) { | ||
return _orderchain.size(); | ||
} | ||
|
||
/// @notice 물류사에 등록된 주문 리스트에서 order 바로 이전의 주문 컨트랙트 주소를 반환한다. | ||
/// @param order 주문 컨트랙트 주소 | ||
/// @return order 이전의 주문 컨트랙트 주소 (address) | ||
function prevOrder(address order) public view returns(address) { | ||
return _orderchain.prevOf(order); | ||
} | ||
|
||
/// @notice 물류사의 수취인 주소를 반환한다. | ||
/// @return 물류사의 수취인 주소 (address) | ||
function recipient() public view returns(address) { | ||
return _recipient; | ||
} | ||
|
||
/// @notice 서비스 컨트랙트 주소를 반환한다. | ||
/// @return 서비스 컨트랙트 주소 (address) | ||
function service() public view returns(address) { | ||
return _service; | ||
} | ||
|
||
/// @notice 물류사 URL을 반환한다. | ||
/// @return 물류사 URL (string) | ||
function url() public view returns(string memory) { | ||
return _url; | ||
} | ||
|
||
/// @notice 주문 상태갱신 알림을 위해 주문 컨트랙트의 submitUpdate를 호출한다. | ||
/// @param order 주문 컨트랙트 주소 | ||
/// @param code 배송상태 코드 번호 | ||
function _submitUpdate(address order, uint256 code) private { | ||
bytes memory cmd = abi.encodeWithSignature("submitOrderUpdate(uint64,uint256)", block.timestamp, code); | ||
address(order)._call(cmd); // 주문 컨트랙트에 트래킹 정보 기록 | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity >=0.6.0 <0.7.0; | ||
|
||
import "./DkargoPrefix.sol"; | ||
import "./authority/Ownership.sol"; | ||
import "./introspection/ERC165/ERC165.sol"; | ||
import "./libs/Address.sol"; | ||
import "./libs/chain/ChainUint64.sol"; | ||
import "./libs/chain/Typedef.sol"; | ||
import "./libs/math/SafeMath256.sol"; | ||
|
||
/// @title DkargoFund | ||
/// @notice 디카르고 펀드 컨트랙트 정의 | ||
/// @author jhhong | ||
contract DkargoFund is Ownership, ERC165, DkargoPrefix { | ||
using Address for address; | ||
using SafeMath256 for uint256; | ||
using ChainUint64 for Typedef.Uint64List; | ||
|
||
/// @dev 변수 선언 | ||
address private _beneficier; // 수취인 주소 | ||
address private _token; // 토큰 컨트랙트 주소 | ||
uint256 private _totals; // 플랜에 기록된 총 인출량, 펀드의 보유 토큰량을 초과할 수 없다. | ||
mapping(uint64 => uint256) private _plans; // 락업 플랜 | ||
Typedef.Uint64List private _planchain; // 락업 플랜 체인 | ||
|
||
/// @notice 수취인 주소 업데이트 이벤트 | ||
/// @param beneficier 수취인 주소 | ||
event BeneficierUpdated(address indexed beneficier); | ||
|
||
/// @notice lock-up 플랜 설정 이벤트 | ||
/// @dev amount = 0이면 lock-up 플랜 제거 이벤트이다. | ||
/// @param time unlock될 시각 (epoch time) | ||
/// @param amount unlock될 양 | ||
event PlanSet(uint64 time, uint256 amount); | ||
|
||
/// @notice 인출 이벤트 | ||
/// @param amount 인출 금액 | ||
event Withdraw(uint256 amount); | ||
|
||
/// @notice 컨트랙트 생성자이다. | ||
/// @param token 토큰 컨트랙트 주소 | ||
/// @param beneficier 수취인 주소 | ||
constructor(address token, address beneficier) public { | ||
require(token != address(0), "DkargoFund: token is null"); | ||
require(beneficier != address(0), "DkargoFund: beneficier is null"); | ||
_setDkargoPrefix("fund"); // 프리픽스 설정 (fund) | ||
_registerInterface(0x946edbed); // INTERFACE ID 등록 (getDkargoPrefix) | ||
_token = token; | ||
_beneficier = beneficier; | ||
} | ||
|
||
/// @notice 인출금액 수취인을 설정한다. | ||
/// @dev 수취인 주소로 EOA, CA 다 설정 가능하다. | ||
/// @param beneficier 설정할 수취인 주소 (address) | ||
function setBeneficier(address beneficier) onlyOwner public { | ||
require(beneficier != address(0), "DkargoFund: beneficier is null"); | ||
require(beneficier != _beneficier, "DkargoFund: should be not equal"); | ||
_beneficier = beneficier; | ||
emit BeneficierUpdated(beneficier); | ||
} | ||
|
||
/// @notice 인출 플랜을 추가한다. | ||
/// @dev amount!=0이면 새 플랜을 추가한다는 의미이다. linkChain 과정이 수행된다. 기존에 설정된 플랜이 있을 경우 덮어쓴다. | ||
/// amount=0이면 플랜을 삭제한다는 의미이다. unlinkChain 과정이 수행된다. 기존에 설정된 플랜이 없을 경우 revert된다. | ||
/// time은 현재 시각(block.timestamp)보다 큰 값이어야 한다. | ||
/// 설정된 플랜들의 모든 amount의 합은 balanceOf(fundCA)를 초과할 수 없다. | ||
/// @param time 인출 가능한 시각 | ||
/// @param amount 인출 가능한 금액 | ||
function setPlan(uint64 time, uint256 amount) onlyOwner public { | ||
require(time > block.timestamp, "DkargoFund: invalid time"); | ||
_totals = _totals.add(amount); // 추가될 플랜 금액을 총 플랜금액에 합산 | ||
_totals = _totals.sub(_plans[time]); // 총 플랜금액에서 기존 설정된 금액을 차감 | ||
require(_totals <= fundAmount(), "DkargoFund: over the limit"); // 총 플랜금액 체크 | ||
_plans[time] = amount; // 플랜 금액 갱신 | ||
emit PlanSet(time, amount); // 이벤트 발생 | ||
if(amount == 0) { // 체인정보 갱신 | ||
_planchain.unlinkChain(time); // 기존에 설정되지 않았을 경우, revert("AddressChain: the node is aleady unlinked") | ||
} else if(_planchain.isLinked(time) == false) { // 새 설정일 경우에만 체인추가, 기존 설정이 있을 경우, 값만 갱신하고 체인 정보는 갱신하지 않음 | ||
_planchain.linkChain(time); | ||
} | ||
} | ||
|
||
/// @notice 토큰을 지정된 수취인에게로 인출한다. | ||
/// @dev 만료되지 않은 index는 인출 불가능하다. revert! | ||
/// 설정되지 않은 (혹은 해제된) 플랜 인덱스에 대해서는 revert! | ||
/// @param index 플랜 인덱스, setPlan에서 넣어줬던 인출 가능 시각이다. | ||
function withdraw(uint64 index) onlyOwner public { | ||
require(index <= block.timestamp, "DkargoFund: an unexpired plan"); | ||
require(_plans[index] > 0, "DkargoFund: plan is not set"); | ||
bytes memory cmd = abi.encodeWithSignature("transfer(address,uint256)", _beneficier, _plans[index]); | ||
bytes memory data = address(_token)._call(cmd); | ||
bool result = abi.decode(data, (bool)); | ||
require(result == true, "DkargoFund: failed to proceed raw-data"); | ||
_totals = _totals.sub(_plans[index]); // 총 플랜금액에서 기존 설정된 금액을 차감 | ||
emit Withdraw(_plans[index]); | ||
_plans[index] = 0; | ||
_planchain.unlinkChain(index); | ||
} | ||
|
||
/// @notice Fund 컨트랙트의 밸런스를 확인한다. | ||
/// @return Fund 컨트랙트의 밸런스 (uint256) | ||
function fundAmount() public view returns(uint256) { | ||
bytes memory data = address(_token)._vcall(abi.encodeWithSignature("balanceOf(address)", address(this))); | ||
return abi.decode(data, (uint256)); | ||
} | ||
|
||
/// @notice 플랜에 기록된 총 금액을 확인한다. | ||
/// @return 플랜에 기록된 총 금액 (uint256) | ||
function totalPlannedAmount() public view returns(uint256) { | ||
return _totals; | ||
} | ||
|
||
/// @notice 플랜 인덱스에 해당하는 인출 금액을 확인한다. | ||
/// @param index 플랜 인덱스, setPlan에서 넣어줬던 인출 가능 시각이다. | ||
/// @return 플랜 인덱스에 해당하는 인출 금액 (uint256) | ||
function plannedAmountOf(uint64 index) public view returns(uint256) { | ||
return _plans[index]; | ||
} | ||
|
||
/// @notice 수취인 주소를 확인한다. | ||
/// @return 수취인 주소 (address) | ||
function beneficier() public view returns(address) { | ||
return _beneficier; | ||
} | ||
|
||
/// @notice 토큰(ERC-20) 주소를 확인한다. | ||
/// @return 토큰 주소 (address) | ||
function token() public view returns(address) { | ||
return _token; | ||
} | ||
} |
Oops, something went wrong.