-
Notifications
You must be signed in to change notification settings - Fork 160
/
ManualApprovalTransferManager.sol
169 lines (148 loc) · 6.6 KB
/
ManualApprovalTransferManager.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
pragma solidity ^0.4.24;
import "./ITransferManager.sol";
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
/**
* @title Transfer Manager module for manually approving or blocking transactions between accounts
*/
contract ManualApprovalTransferManager is ITransferManager {
using SafeMath for uint256;
//Address from which issuances come
address public issuanceAddress = address(0);
//Address which can sign whitelist changes
address public signingAddress = address(0);
bytes32 public constant TRANSFER_APPROVAL = "TRANSFER_APPROVAL";
//Manual approval is an allowance (that has been approved) with an expiry time
struct ManualApproval {
uint256 allowance;
uint256 expiryTime;
}
//Manual blocking allows you to specify a list of blocked address pairs with an associated expiry time for the block
struct ManualBlocking {
uint256 expiryTime;
}
//Store mappings of address => address with ManualApprovals
mapping (address => mapping (address => ManualApproval)) public manualApprovals;
//Store mappings of address => address with ManualBlockings
mapping (address => mapping (address => ManualBlocking)) public manualBlockings;
event AddManualApproval(
address indexed _from,
address indexed _to,
uint256 _allowance,
uint256 _expiryTime,
address indexed _addedBy
);
event AddManualBlocking(
address indexed _from,
address indexed _to,
uint256 _expiryTime,
address indexed _addedBy
);
event RevokeManualApproval(
address indexed _from,
address indexed _to,
address indexed _addedBy
);
event RevokeManualBlocking(
address indexed _from,
address indexed _to,
address indexed _addedBy
);
/**
* @notice Constructor
* @param _securityToken Address of the security token
* @param _polyAddress Address of the polytoken
*/
constructor (address _securityToken, address _polyAddress)
public
Module(_securityToken, _polyAddress)
{
}
/**
* @notice This function returns the signature of configure function
*/
function getInitFunction() public pure returns (bytes4) {
return bytes4(0);
}
/** @notice Used to verify the transfer transaction and allow a manually approved transqaction to bypass other restrictions
* @param _from Address of the sender
* @param _to Address of the receiver
* @param _amount The amount of tokens to transfer
* @param _isTransfer Whether or not this is an actual transfer or just a test to see if the tokens would be transferrable
*/
function verifyTransfer(address _from, address _to, uint256 _amount, bytes /* _data */, bool _isTransfer) public returns(Result) {
// function must only be called by the associated security token if _isTransfer == true
require(_isTransfer == false || msg.sender == securityToken, "Sender is not the owner");
// manual blocking takes precidence over manual approval
if (!paused) {
/*solium-disable-next-line security/no-block-members*/
if (manualBlockings[_from][_to].expiryTime >= now) {
return Result.INVALID;
}
/*solium-disable-next-line security/no-block-members*/
if ((manualApprovals[_from][_to].expiryTime >= now) && (manualApprovals[_from][_to].allowance >= _amount)) {
if (_isTransfer) {
manualApprovals[_from][_to].allowance = manualApprovals[_from][_to].allowance.sub(_amount);
}
return Result.VALID;
}
}
return Result.NA;
}
/**
* @notice Adds a pair of addresses to manual approvals
* @param _from is the address from which transfers are approved
* @param _to is the address to which transfers are approved
* @param _allowance is the approved amount of tokens
* @param _expiryTime is the time until which the transfer is allowed
*/
function addManualApproval(address _from, address _to, uint256 _allowance, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) {
require(_to != address(0), "Invalid to address");
/*solium-disable-next-line security/no-block-members*/
require(_expiryTime > now, "Invalid expiry time");
require(manualApprovals[_from][_to].allowance == 0, "Approval already exists");
manualApprovals[_from][_to] = ManualApproval(_allowance, _expiryTime);
emit AddManualApproval(_from, _to, _allowance, _expiryTime, msg.sender);
}
/**
* @notice Adds a pair of addresses to manual blockings
* @param _from is the address from which transfers are blocked
* @param _to is the address to which transfers are blocked
* @param _expiryTime is the time until which the transfer is blocked
*/
function addManualBlocking(address _from, address _to, uint256 _expiryTime) public withPerm(TRANSFER_APPROVAL) {
require(_to != address(0), "Invalid to address");
/*solium-disable-next-line security/no-block-members*/
require(_expiryTime > now, "Invalid expiry time");
require(manualBlockings[_from][_to].expiryTime == 0, "Blocking already exists");
manualBlockings[_from][_to] = ManualBlocking(_expiryTime);
emit AddManualBlocking(_from, _to, _expiryTime, msg.sender);
}
/**
* @notice Removes a pairs of addresses from manual approvals
* @param _from is the address from which transfers are approved
* @param _to is the address to which transfers are approved
*/
function revokeManualApproval(address _from, address _to) public withPerm(TRANSFER_APPROVAL) {
require(_to != address(0), "Invalid to address");
delete manualApprovals[_from][_to];
emit RevokeManualApproval(_from, _to, msg.sender);
}
/**
* @notice Removes a pairs of addresses from manual approvals
* @param _from is the address from which transfers are approved
* @param _to is the address to which transfers are approved
*/
function revokeManualBlocking(address _from, address _to) public withPerm(TRANSFER_APPROVAL) {
require(_to != address(0), "Invalid to address");
delete manualBlockings[_from][_to];
emit RevokeManualBlocking(_from, _to, msg.sender);
}
/**
* @notice Returns the permissions flag that are associated with ManualApproval transfer manager
*/
function getPermissions() public view returns(bytes32[]) {
bytes32[] memory allPermissions = new bytes32[](1);
allPermissions[0] = TRANSFER_APPROVAL;
return allPermissions;
}
}