1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | pragma solidity ^0.4.19; contract Owned{ address public owner; event TransferOwnership(address oldaddr, address newaddr); modifier onlyOwner(){ require(msg.sender == owner); _; } function Owned(){ owner = msg.sender; } function transferOwnership(address _new) onlyOwner{ address oldaddr = owner; owner = _new; TransferOwnership(oldaddr, owner); } } contract Member is Owned{ address public coin; MemberStatus[] public status; mapping(address => History) public tradingHistory; struct MemberStatus{ string name; uint times; uint sum; int8 rate; } struct History{ uint times; uint sum; uint statusIndex; } modifier onlyCoin(){ require(msg.sender == coin); _; } function setCoin(address _addr) onlyOwner{ coin = _addr; } function pushStatus(string _name, uint _times, uint _sum, int8 _rate) onlyOwner{ status.push( MemberStatus({ name: _name, times: _times, sum: _sum, rate: _rate }) ); } function editStatus(uint _index, string _name, uint _times, uint _sum, int8 _rate) onlyOwner{ if(_index < status.length){ status[_index].name = _name; status[_index].times = _times; status[_index].sum = _sum; status[_index].rate = _rate; } } function updateHistory(address _member, uint _value) onlyCoin{ tradingHistory[_member].times += 1; tradingHistory[_member].sum += _value; uint index; for(uint i = 0; i < status.length; i++){ if(tradingHistory[_member].times >= status[i].times && tradingHistory[_member].sum >= status[i].sum){ index = i; } } tradingHistory[_member].statusIndex = index; } function getCashackRate(address _member) constant returns(int8 rate){ rate = status[tradingHistory[_member].statusIndex].rate; } } contract CrocusCoin is Owned{ string public name; string public symbol; uint8 public decimals; uint public totalSupply; mapping(address => uint) public balanceOf; mapping(address => int8) public blackList; mapping(address => Member) public members; event Transfer(address indexed from, address indexed to, uint value); event Blacklisted(address indexed target); event DeleteFromBlacklist(address indexed target); event RejectedPaymentToBlacklistedAddr(address indexed from, address indexed to, uint value); event RejectedPaymentFromBlacklistedAddr(address indexed from, address indexed to, uint value); event SetCashback(address indexed addr, int8 rate); event Cashback(address indexed from, address indexed to, uint value); function CrocusCoin(uint _supply, string _name, string _symbol, uint8 _decimals){ balanceOf[msg.sender] = _supply; name = _name; symbol = _symbol; decimals = _decimals; totalSupply = _supply; owner = msg.sender; } function blacklisting(address _addr) onlyOwner{ blackList[_addr] = 1; Blacklisted(_addr); } function deleteFromBlacklist(address _addr) onlyOwner{ blackList[_addr] = 0; DeleteFromBlacklist(_addr); } function setMembers(Member _members){ members[msg.sender] = Member(_members); } function transfer(address _to, uint _value){ require(balanceOf[msg.sender] >= _value); require(balanceOf[_to] + _value >= balanceOf[_to]); if(blackList[msg.sender] > 0){ RejectedPaymentFromBlacklistedAddr(msg.sender, _to, _value); } else if(blackList[_to] > 0){ RejectedPaymentToBlacklistedAddr(msg.sender, _to, _value); } else{ uint cashback = 0; if(members[_to] > address(0)){ cashback = _value / 100 * uint(members[_to].getCashackRate(msg.sender)); members[_to].updateHistory(msg.sender, _value); } } balanceOf[msg.sender] -= (_value - cashback); balanceOf[_to] += (_value - cashback); Transfer(msg.sender, _to, _value); Cashback(_to, msg.sender, cashback); } } | cs |
Owned는 소유자 관리용 계약을 의미한다.
onlyOwner 함수 제어자는 컨트랙트 소유자를 확인하는 용도이다.
Owned 생성자는 owner가 msg.sender 즉, 최초 컨트랙트 생성자가 owner이 된다.
transferOwnership로 인해 소유자만이 새로운 사람으로 소유자 변경이 가능하게 된다.
Member 컨트랙트는 Owned를 상속하고 있다.
현재 코인의 주인을 나타내는 coin가 있고,
MemberStatus 구조체는 등급을 나타내는 구조체이다.(브론즈, 실버, 골드 등등)
name는 등급 이름을, times는 등급에 필요한 거래 횟수를, sum은 등급에 필요한 거래 총액을 rate는 캐시백 받을 수 있는 비율이다.
History 구조체에서 times는 거래 횟수를 sum은 거래 금액을 statusIndex는 등급 인덱스를 나타낸다.
onlyCoin 함수 제어자는 해당하는 코인이 msg.sender것이어야 한다.
setCoin은 토큰 주소를 설정해주는 함수이고
pushStatus는 등급을 나타내는 것들을 추가해주는 함수이다. (즉, 브론즈, 실버, 골드 다음 플레티넘 같은 것들을 추가하는 과정)
editStatus는 말그대로 등급의 특정 조건들을 변경시켜준다.
updateHistory는 해당하는 멤버의 거래수를 +1, 거래 금액을 += _value 해준다.
그리고 이제 이 사람의 등급이 바뀌는지 확인하기 위해 아래 for문 과정을 거친다.
i의 인덱스가 처음부터 낮은 등급을 의미하니 해당하는 등급을 찾아줄 수 있게 된다.
마지막으로 tradingHistory[_member].statusIndex = index를 통해 등급을 업데이트 해준다.
getCashbackRate는 캐시백 받을 비율을 계산해주는 함수이다.
CrocusCoin은 Owned을 상속하고
name은 토큰 이름, symbol은 토큰 단위, decimals은 소수점 이하 자릿수, totalSupply는 토큰 총 발행량을 의미한다.
그리고 balanceOf는 해당하는 주소의 잔고를 의미하고 blackList는 블랙리스트 주소들을, members는 멤버들을 의미한다.
CrocusCoin 생성자에 의해 각 값들이 대입되고
blacklisting 및 deleteFromBlacklist에 의해 블랙리스트를 설정 및 해제할 수 있다.
setMembers에 의해 멤버를 만들어줄 수 있고
transfer은 두 require에 의해 transfer 조건을 판단하게 된다.
아래 if, else if에 의해 보내는 이, 받는 이 둘중 한명이라도 블랙리스트라면 transfer은 불가능 하다.
else부분에 의해 캐시백을 설정하게 되고
아래에 의해 transfer 절차가 이루어진다.
'Applied > Blockchain' 카테고리의 다른 글
Solidity에서 스트링 비교 (0) | 2018.05.16 |
---|---|
Solidity를 이용한 존재 증명 계약 (0) | 2018.05.15 |
Solidity 블랙리스트 구현 (0) | 2018.05.05 |
Sollidity 토큰 Contract 예제문 (0) | 2018.05.04 |
Solidity 기초 예제코드 및 분석- 3 (0) | 2018.05.02 |