-
Notifications
You must be signed in to change notification settings - Fork 2
/
MonethaGateway.sol
205 lines (170 loc) · 7.09 KB
/
MonethaGateway.sol
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
pragma solidity ^0.4.24;
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/lifecycle/Destructible.sol";
import "openzeppelin-solidity/contracts/lifecycle/Pausable.sol";
import "openzeppelin-solidity/contracts/ownership/Contactable.sol";
import "monetha-utility-contracts/contracts/Restricted.sol";
import "monetha-loyalty-contracts/contracts/IMonethaVoucher.sol";
import "./GenericERC20.sol";
/**
* @title MonethaGateway
*
* MonethaGateway forward funds from order payment to merchant's wallet and collects Monetha fee.
*/
contract MonethaGateway is Pausable, Contactable, Destructible, Restricted {
using SafeMath for uint256;
string constant VERSION = "0.6";
/**
* Fee permille of Monetha fee.
* 1 permille (‰) = 0.1 percent (%)
* 15‰ = 1.5%
*/
uint public constant FEE_PERMILLE = 15;
uint public constant PERMILLE_COEFFICIENT = 1000;
/**
* Address of Monetha Vault for fee collection
*/
address public monethaVault;
/**
* Account for permissions managing
*/
address public admin;
/**
* Monetha voucher contract
*/
IMonethaVoucher public monethaVoucher;
/**
* Max. discount permille.
* 10 permille = 1 %
*/
uint public MaxDiscountPermille;
event PaymentProcessedEther(address merchantWallet, uint merchantIncome, uint monethaIncome);
event PaymentProcessedToken(address tokenAddress, address merchantWallet, uint merchantIncome, uint monethaIncome);
event MonethaVoucherChanged(
address indexed previousMonethaVoucher,
address indexed newMonethaVoucher
);
event MaxDiscountPermilleChanged(uint prevPermilleValue, uint newPermilleValue);
/**
* @param _monethaVault Address of Monetha Vault
*/
constructor(address _monethaVault, address _admin, IMonethaVoucher _monethaVoucher) public {
require(_monethaVault != 0x0);
monethaVault = _monethaVault;
setAdmin(_admin);
setMonethaVoucher(_monethaVoucher);
setMaxDiscountPermille(700); // 70%
}
/**
* acceptPayment accept payment from PaymentAcceptor, forwards it to merchant's wallet
* and collects Monetha fee.
* @param _merchantWallet address of merchant's wallet for fund transfer
* @param _monethaFee is a fee collected by Monetha
*/
/**
* acceptPayment accept payment from PaymentAcceptor, forwards it to merchant's wallet
* and collects Monetha fee.
* @param _merchantWallet address of merchant's wallet for fund transfer
* @param _monethaFee is a fee collected by Monetha
*/
function acceptPayment(address _merchantWallet,
uint _monethaFee,
address _customerAddress,
uint _vouchersApply,
uint _paybackPermille)
external payable onlyMonetha whenNotPaused returns (uint discountWei){
require(_merchantWallet != 0x0);
uint price = msg.value;
// Monetha fee cannot be greater than 1.5% of payment
require(_monethaFee >= 0 && _monethaFee <= FEE_PERMILLE.mul(price).div(1000));
discountWei = 0;
if (monethaVoucher != address(0)) {
if (_vouchersApply > 0 && MaxDiscountPermille > 0) {
uint maxDiscountWei = price.mul(MaxDiscountPermille).div(PERMILLE_COEFFICIENT);
uint maxVouchers = monethaVoucher.fromWei(maxDiscountWei);
// limit vouchers to apply
uint vouchersApply = _vouchersApply;
if (vouchersApply > maxVouchers) {
vouchersApply = maxVouchers;
}
(, discountWei) = monethaVoucher.applyDiscount(_customerAddress, vouchersApply);
}
if (_paybackPermille > 0) {
uint paybackWei = price.sub(discountWei).mul(_paybackPermille).div(PERMILLE_COEFFICIENT);
if (paybackWei > 0) {
monethaVoucher.applyPayback(_customerAddress, paybackWei);
}
}
}
uint merchantIncome = price.sub(_monethaFee);
_merchantWallet.transfer(merchantIncome);
monethaVault.transfer(_monethaFee);
emit PaymentProcessedEther(_merchantWallet, merchantIncome, _monethaFee);
}
/**
* acceptTokenPayment accept token payment from PaymentAcceptor, forwards it to merchant's wallet
* and collects Monetha fee.
* @param _merchantWallet address of merchant's wallet for fund transfer
* @param _monethaFee is a fee collected by Monetha
* @param _tokenAddress is the token address
* @param _value is the order value
*/
function acceptTokenPayment(
address _merchantWallet,
uint _monethaFee,
address _tokenAddress,
uint _value
)
external onlyMonetha whenNotPaused
{
require(_merchantWallet != 0x0);
// Monetha fee cannot be greater than 1.5% of payment
require(_monethaFee >= 0 && _monethaFee <= FEE_PERMILLE.mul(_value).div(1000));
uint merchantIncome = _value.sub(_monethaFee);
GenericERC20(_tokenAddress).transfer(_merchantWallet, merchantIncome);
GenericERC20(_tokenAddress).transfer(monethaVault, _monethaFee);
emit PaymentProcessedToken(_tokenAddress, _merchantWallet, merchantIncome, _monethaFee);
}
/**
* changeMonethaVault allows owner to change address of Monetha Vault.
* @param newVault New address of Monetha Vault
*/
function changeMonethaVault(address newVault) external onlyOwner whenNotPaused {
monethaVault = newVault;
}
/**
* Allows other monetha account or contract to set new monetha address
*/
function setMonethaAddress(address _address, bool _isMonethaAddress) public {
require(msg.sender == admin || msg.sender == owner);
isMonethaAddress[_address] = _isMonethaAddress;
emit MonethaAddressSet(_address, _isMonethaAddress);
}
/**
* setAdmin allows owner to change address of admin.
* @param _admin New address of admin
*/
function setAdmin(address _admin) public onlyOwner {
require(_admin != address(0));
admin = _admin;
}
/**
* setAdmin allows owner to change address of Monetha voucher contract. If set to 0x0 address, discounts and paybacks are disabled.
* @param _monethaVoucher New address of Monetha voucher contract
*/
function setMonethaVoucher(IMonethaVoucher _monethaVoucher) public onlyOwner {
if (monethaVoucher != _monethaVoucher) {
emit MonethaVoucherChanged(monethaVoucher, _monethaVoucher);
monethaVoucher = _monethaVoucher;
}
}
/**
* setMaxDiscountPermille allows Monetha to change max.discount percentage
* @param _maxDiscountPermille New value of max.discount (in permille)
*/
function setMaxDiscountPermille(uint _maxDiscountPermille) public onlyOwner {
require(_maxDiscountPermille <= PERMILLE_COEFFICIENT);
emit MaxDiscountPermilleChanged(MaxDiscountPermille, _maxDiscountPermille);
MaxDiscountPermille = _maxDiscountPermille;
}
}